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);
    }
}
posted @ 2021-08-17 21:33  wlhp  阅读(12)  评论(0)    收藏  举报