暑假D1 T3 play(加速排序)

题目大意

这个位面存在编号为1~2N的2N个斗士,他们正为争夺斗士大餐展开R轮PVP,每个斗士i都有一个固有APM ai,和一个初始斗士大餐储量 bi。每轮开始前以及最后一轮结束之后,2N个斗士会重新按照各自斗士大餐的储量进行排序(斗士大餐储量相同时编号小的靠前),每轮中,第1名和第2名PVP,第3名和第4名PVP,……第2k-1名和第2k名PVP,第2N-1名和第2N名PVP。而每场一对一的PVP都非常无聊,总是两个斗士中APM高的获胜,另一方失败;或者APM相同的两方取得平手。每轮赛后获胜方获得2份斗士大餐,平均双方均获得1份斗士大餐。

输入格式

第一行两个整数N、R;
第二行2N个整数,bi;
第三行2N个整数, ai;

输出格式

2N个整数,R轮比赛后排名从小到大的各斗士编号;

样例输入

10 10
0 10 49 24 7 1 64 8 52 81 4 9 40 17 52 17 40 0 97 77
0 1 0 1 1 1 0 2 1 0 0 2 1 1 2 0 1 1 1 0

样例输出

19 10 20 7 15 9 13 17 3 4 14 12 8 2 16 5 6 18 11 1

数据范围


10%的数据:N≤10,R≤10,ai≤1e8,bi≤1e8
30%的数据:N≤1e2,R≤60,ai≤1e8,bi≤1e8
70%的数据:N≤1e4,R≤60,ai≤1e8,bi≤1e8
100%的数据:N≤1e5,R≤60,ai≤1e8,bi≤1e8

思路

最初很容易可以想到用快排之后,直接模拟就好,复杂度O(R*logn)

思考优化排序,将赢的、输的、平的分成三个队伍,对于每个队伍他bi增加的值相同,而一开始又有顺序,所以在队伍中仍有单调性。

需要注意的是,在顶端的人bi是比较小的,所以在重新确定p数组时需要倒序插入。

#include<bits/stdc++.h>
using namespace std;

const int maxn=200005;
int n,r,top1,top2,top3;
struct person{
    int a,b,id;
}p[maxn],winner[maxn],loser[maxn],equel[maxn];

template<class T>inline void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

bool cmp(person s,person t){
    if(s.b==t.b) return s.id<t.id;
    return s.b>t.b;
}

bool cmp1(person s,person t){
    if(s.b==t.b) return s.id>t.id;
    return s.b<t.b;
}

int main(){
    freopen("play.in","r",stdin);
    freopen("play.out","w",stdout);
    scanf("%d%d",&n,&r);
    for(int i=1;i<=2*n;i++){
        scanf("%d",&p[i].b);
        p[i].id=i;
    }
    for(int i=1;i<=2*n;i++) scanf("%d",&p[i].a);
    sort(p+1,p+2*n+1,cmp);
    while(r--){
        for(int i=1;i<=2*n;i+=2)
         if(p[i].a>p[i+1].a){
             p[i].b+=2;
             winner[++top1]=p[i];
             loser[++top2]=p[i+1];
         }
         else if(p[i].a<p[i+1].a){
             p[i+1].b+=2;
             winner[++top1]=p[i+1];
             loser[++top2]=p[i];
         }
         else {
             p[i].b++;p[i+1].b++;
             equel[++top3]=p[i];
             equel[++top3]=p[i+1];
         }
        for(int i=2*n;i;i--){
            if(top1){
                if(top2){
                    if(cmp1(winner[top1],loser[top2])){
                      if(!top3) p[i]=winner[top1--];
                      else if(cmp1(winner[top1],equel[top3])) p[i]=winner[top1--];
                      else p[i]=equel[top3--];
                    }
                    else {
                        if(!top3) p[i]=loser[top2--];
                        else if(cmp1(loser[top2],equel[top3])) p[i]=loser[top2--];
                        else p[i]=equel[top3--];
                    }
                } 
                else if(!top3) p[i]=winner[top1--];
                else if(cmp1(winner[top1],equel[top3])) p[i]=winner[top1--];
                else p[i]=equel[top3--];
            } 
            else{
                if(top2){
                    if(!top3) p[i]=loser[top2--];
                    else if(cmp1(loser[top2],equel[top3])) p[i]=loser[top2--];
                    else p[i]=equel[top3--];
                }
                else p[i]=equel[top3--];
            }
        }
    }
    for(int i=1;i<=2*n;i++) printf("%d ",p[i].id);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sto324/p/11160684.html