CF1038C题解

思路

这是一道贪心+模拟题。

首先输入 AABB 的数列,分别用一个优先队列(大根堆)存下来。


定义 nownow 表示当前轮到谁了,00 表示 AA11 表示 BB,每次操作完将 now1now\oplus 1(其中 \oplus 表示按位异或)。

定义 ansans 表示 A,BA,B 的分数差。


对于 AA 的数列所对应的优先队列(以下简称 PAP_A)的队首与 BB 的数列所对应的优先队列(以下简称 PBP_B)的队首做比较:

  • 如果 PAP_A 的队首更大,那么看 nownow 的值:
    \circ 如果 now=1now=1 则表示 BBPAP_A 的队首删去,弹出 PAP_A 的队首。
    \circ 如果 now=0now=0 则表示 AAPAP_A 的队首加入自己的分数,即 ans+PAans+P_A 的队首的分数,弹出 PAP_A 的队首。
  • 如果 PBP_B 的队首更大,那么看 nownow 的值:
    \circ 如果 now=1now=1 则表示 BBPBP_B 的队首加入自己的分数,即 ansPBans-P_B 的队首的分数,弹出 PBP_B 的队首。
    \circ 如果 now=0now=0 则表示 AAPBP_B 的队首删去,弹出 PBP_B 的队首。

最后输出 ansans 即可。

程序实现

其实没啥细节,建议自己实现。

#include<bits/stdc++.h>
using namespace std;
int n,now;
long long ans;
priority_queue<int>A;
priority_queue<int>B;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int a;
		scanf("%d",&a);
		A.push(a);
	}
	for(int i=1;i<=n;i++){
		int b;
		scanf("%d",&b);
		B.push(b);
	}
	while(!A.empty()&&!B.empty()){
		int a=A.top(),b=B.top();
		A.pop(),B.pop();
		if(a>b){
			if(!now) ans+=a;
			B.push(b);
		}
		else if(a<b){
			if(now) ans-=b;
			A.push(a);
		}
		else{
			if(!now) ans+=a,B.push(b);
			else ans-=b,A.push(a);
		}
		now^=1;
	}
	while(!A.empty()){
		int a=A.top();
		A.pop();
		if(!now) ans+=a;
		now^=1;
	}
	while(!B.empty()){
		int b=B.top();
		B.pop();
		if(now) ans-=b;
		now^=1;
	}
	return !printf("%lld",ans);
}
posted @ 2022-11-08 22:05  fengxiaoyi  阅读(18)  评论(0)    收藏  举报  来源