题解:P15081 [ICPC 2024 Chengdu R] Grand Prix of Ballance

· · 题解

P15081题解

题意简述

m 个人参加由 n 个关卡组成的比赛,现在给出三种描述:

第一种,表示一个关卡开启。

第二种,表示一位选手完成了某关卡。

第三种,表示一位选手放弃了某关卡。

但玩家只能完成或放弃当前正在进行的关卡,关卡不能重复开启,当一位玩家完成或放弃了某关卡后,该玩家针对该关卡的后续所有消息都将被忽略。

求每位参与者的总积分,降序输出。

解题思路

理解题意之后直接模拟,造一个玩家结构体,存放该玩家的编号、总积分、当前关卡的状态(未知、完成、或者放弃)。

按照题意处理每个描述,注意特判

最后排序输出即可~。

(多测不清空见祖宗)

还不明白?看代码!

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,m,q,n;
int id,x;
struct nnd{
    int jf,id,zt;//积分、id、当前关卡状态:0未知,nw完成,-nw放弃(nw为当前关卡编号)
}a[100010];
bool cmp(nnd x,nnd y){
    return x.jf==y.jf?(x.id<y.id):(x.jf>y.jf);//积分作为第一关键字,编号作为第二关键字
}
signed main(){
    scanf("%lld",&T);
    while(T--){
        scanf("%lld %lld %lld",&n,&m,&q);//读入
        for(int i=1;i<=m;i++) a[i].id=i,a[i].jf=a[i].zt=0;//每位玩家的id重新记下,积分和当前关卡状态清零
        int nw=0,t=0;//当前关卡、通过人数(初始值为0)
        for(int i=1;i<=q;i++){
            int op,id,x;
            scanf("%lld",&op);
            if(op==1){
                if(nw>n) continue;//判断是否当前关卡都不在n关的范围内了,是则跳过
                scanf("%lld",&nw),t=0;
            }
            else if(op==2){
                scanf("%lld %lld",&id,&x);
                if(x!=nw||abs(a[id].zt)==nw)//当前关不在n关范围内或该玩家已经有了相应状态(完成或放弃)
                    continue;//直接跳过
                a[id].zt=nw;//状态赋值为nw,表示已经完成
                a[id].jf+=(m-t++);//积分累计,完成人数加一
            }
            else if(op==3){
                scanf("%lld %lld",&id,&x);
                if(x!=nw||abs(a[id].zt)==nw) continue;//特判同上
                a[id].zt=-nw;//状态赋值为-nw,表示放弃该关卡
            }
        }
        sort(a+1,a+m+1,cmp);//排序
        for(int i=1;i<=m;i++) printf("%lld %lld\n",a[i].id,a[i].jf);//输出
    }
    return (0^0);//卖个萌(
}

你学会了吗。