2021杭电第九场
1003: Dota2 Pro Circuit
看数据范围可以\(n^2\)的暴力做法
那么考虑如何贪心的拿取能排名最优,对于某个分数 \(a\) 最好排名是:首先加上最大值,然后我们希望所有其他数都小于他,那么贪心的依次将小的值加给大的分数,如果大的分数加上小的值仍要比当前这个分数大,那么没办法了,就要考虑将最后的一个最大值加上当前剩下的最大值,那么现在显然其他的分数加上的值都小了一位,一定满足了,继续贪心一直到放完。也就是说当把最大值给了这个分数后,剩余的值依次从小到大给从大到小的分数,如果某个分数 \(b\) 加上值比 \(a\) 大了,那么一定会有一个分数在 \(a\) 前面,那么我把最大的值加上最大的分数,放到 \(a\) 前面,那么现在 \(b\) 加上的值是上一个分数加的值,那么一定是小于 \(a\) 的,那么继续贪心下去就行了。
相反的也是一样的思路
const int maxn = 5e3 + 10;
int b[maxn], n;
pair<int, int> a[maxn], ans[maxn];
void run() {
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n);
for(int i = 1; i <= n; ++ i) scanf("%d", &a[i].first), a[i].second = i;
for(int i = 1; i <= n; ++ i) scanf("%d", &b[i]);//b[1] > b[0]
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; ++ i) {
int now = a[i].first + b[1], l1 = n, l2 = n, down = 2, cnt = 0;
for(int j = n; j >= 1 && l2 >= down; -- j) {
if(j == i) continue;
if(a[j].first + b[l2] > now) cnt ++, down ++;
else l2 --;
}
ans[a[i].second].first = cnt + 1;
now = a[i].first + b[n], l1 = 1, l2 = 1, down = n - 1, cnt = 0;
for(int j = 1; j <= n && l2 <= down; ++ j) {
if(j == i) continue;
if(a[j].first + b[l2] <= now) cnt ++, down --;
else l2 ++;
}
ans[a[i].second].second = n - cnt;
}
for(int i = 1; i <= n; ++ i) printf("%d %d\n", ans[i].first, ans[i].second);
}
}

浙公网安备 33010602011771号