ζ

CF873E-Awards For Contestants

    题解

题目大意:一次比赛中,第i个选手解决了a[i]个问题。现在要给这些选手评奖,奖项分一二三等。每个选手可以获得一个奖项,也可以不获奖,但每一种奖项都需要有人获得。要求解决题数更多的人获得的奖项不比解决人数较少的人差,且每一种奖项的获奖人数都不超过另外任意一种奖项的两倍。问区分度最佳的评奖方案是什么。

区分度最佳:

  • 获一等奖且解决问题最少的人解决的题数要尽可能地多于获二等奖且解决问题最多的人解决的题数

  • 在满足上述条件的情况下,获二等奖且解决问题最少的人解决的题数要尽可能地多于获三等奖且解决问题最多的人解决的题数

  • 在满足上述条件的情况下,获三等奖且解决问题最少的人解决的题数要尽可能地多于未获奖且解决问题最多的人解决的题数

本质上就是将每个人的过题数从大到小排序,然后在排好的序列中插3个隔板,(但各隔板之间的子段长度有限制)。用三层for循环来枚举这三个隔板的位置即可。

但是这样直接枚举会超时,需要剪枝。如果枚举当前第一块隔板的位置比之前枚举到的最优位置要差,那这个位置肯定不会取。所谓“最优位置”,就是这个位置的题数跟它下个位置的题数的差最大。如果当前位置跟之前枚举到的最优位置一样优,那要比较下一块隔板有没有比之前隔板更优的位置。放置到最后一块隔板的时候,可以用ST来求最后剩的那个区间的最优值来判断需不需要放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <bits/stdc++.h>
using namespace std;
struct node
{
int a, num;
bool operator<(const node &x) const
{
return a > x.a;
}
} p[3005];
int n, res[3005], st[30][3005];
void init()
{
int i, j, t = log2(n);
for (i = 1; i <= n; i++)
st[0][i] = p[i].a - p[i + 1].a;
for (j = 1; j <= t; j++)
{
for (i = 1; i <= n - (1 << j) + 1; i++)
st[j][i] = max(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
}
}
int maxs(int l, int r)
{
int t = log2(r - l + 1);
return max(st[t][l], st[t][r - (1 << t) + 1]);
}
int main()
{
int i, j, k, e1, e2, e3, d12 = -1, d23 = -1, d34 = -1, lj, rj, lk, rk;
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
scanf("%d", &p[i].a);
p[i].num = i;
}
sort(p + 1, p + 1 + n);
p[n + 1].a = 0;
init();
bool flag1, flag2;
for (i = 1; i <= n - 2; i++)
{
lj = i + ((i + 1) >> 1);
rj = min(n - 1, i + (i << 1));
flag1 = (d12 < p[i].a - p[i + 1].a);
if (d12 <= p[i].a - p[i + 1].a && lj <= rj)
{
for (j = lj; j <= rj; j++)
{
lk = j + max((i + 1) >> 1, (j - i + 1) >> 1);
rk = min(n, j + min(i << 1, (j - i) << 1));
flag2 = (d23 <= p[j].a - p[j + 1].a);
if ((d12 < p[i].a - p[i + 1].a || d23 <= p[j].a - p[j + 1].a) && lk <= rk)
{
if (d12 < p[i].a - p[i + 1].a || d23 < p[j].a - p[j + 1].a || d34 < maxs(lk, rk))
{
e1 = i;
e2 = j;
d12 = p[i].a - p[i + 1].a;
d23 = p[j].a - p[j + 1].a;
d34 = -1;
for (k = lk; k <= rk; k++)
{
if (d34 < p[k].a - p[k + 1].a)
{
d34 = p[k].a - p[k + 1].a;
e3 = k;
}
}
}
}
}
}
}
for (i = 1; i <= e1; i++)
res[p[i].num] = 1;
for (i = e1 + 1; i <= e2; i++)
res[p[i].num] = 2;
for (i = e2 + 1; i <= e3; i++)
res[p[i].num] = 3;
for (i = e3 + 1; i <= n; i++)
res[p[i].num] = -1;
for (i = 1; i <= n; i++)
printf("%d ", res[i]);
return 0;
}
页阅读量:  ・  站访问量:  ・  站访客数: