1 条题解

  • 0
    @ 2024-2-24 17:21:23

    这一题暴力模拟+排序的话,很显然会超时

    考虑优化排序,我们可以在输入完数据后先进行一次排序,然后模拟比赛过程,模拟时除了更新分数,顺便处理出两个队列,分别存储胜者和败者,两个队列中的元素仍然能够保持有序,然后再将两个队列归并回原数组中。这一过程是O(nr)O(nr)级别的,不会超时。

    AC代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const ll N=1e5+5;
    ll n,r,q;
    struct node{
    	ll s,w,id; // s是score即分数,w是实力值,id顾名思义
    }a[2*N];
    bool cmp(node x,node y){
    	return x.s==y.s?x.id<y.id:x.s>y.s; // 按照题目中给出的要求排序
    }
    void merge(){
    	for(ll i=1;i<=r;i++){
    		queue<node> p1,p2;
    		for(ll i=1;i<=2*n;i+=2) // 模拟比赛过程,并处理出胜者和败者
    			if(a[i].w>a[i+1].w)
    				a[i].s++,p1.push(a[i]),p2.push(a[i+1]);
    			else
    				a[i+1].s++,p1.push(a[i+1]),p2.push(a[i]);
    		for(ll i=1;i<=2*n;i++) // 归并过程
    			if(p1.empty())
    				a[i]=p2.front(),p2.pop();
    			else if(p2.empty())
    				a[i]=p1.front(),p1.pop();
    			else if(cmp(p1.front(),p2.front()))
    				a[i]=p1.front(),p1.pop();
    			else
    				a[i]=p2.front(),p2.pop();
    	}
    }
    int main(){
    	scanf("%lld%lld%lld",&n,&r,&q);
    	for(ll i=1;i<=2*n;i++)
    		scanf("%lld",&a[i].s),a[i].id=i;
    	for(ll i=1;i<=2*n;i++)
    		scanf("%lld",&a[i].w);
    	sort(a+1,a+1+2*n,cmp); // 先排序
    	merge();
    	printf("%lld",a[q].id); // 最后输出第q名的id
    	return 0;
    }
    

    归并过程中将队列中的nodenode直接赋值到aa数组中时是不会报错的,并不需要重载=运算符(亏我一开始还多写了👀️ )

    最后提醒大家一定不要看错数据范围,我一开始看到了50%那里把N赋成了1e4👀️ 后来RE了排查半天才改过来👀️

    • 1

    信息

    ID
    668
    时间
    500ms
    内存
    125MiB
    难度
    7
    标签
    递交数
    269
    已通过
    58
    上传者