CF1038C Gambling
CF1038C Gambling
题目大意:
两个人\(A,B\)玩游戏,每个人有1个长度为\(n\)的序列,每次一个人可以从序列中拿一个数并加入自己的分数,或者把对手序列中没选的数中去掉一个,这两个人都足够聪明,求\(A\)分数与\(B\)分数的差
输入格式:
第一行一个整数\(n\)
第二行\(n\)个整数,表示A的序列
第三行\(n\)个整数,表示B的序列
输出格式:
一个整数,表示\(A\)分数与\(B\)分数的差
题解:
看到”足够聪明“就开始想贪心。
贪心这个东西,就是直觉好的人一眼切,直觉不好的人反复错。
对于这道题,贪心策略非常好想也非常好证明。如果当前我方剩下的最大数要比对面剩下的最大数大,那对面怎么拿,我们都是赚的,所以这时取我方最大的。反之,我们怎么拿,只要对面把对面最大的拿走,我们都是亏的。所以贪心策略就出来了。
至于实时维护最大值,可以用堆来实现。
代码:
#include<cstdio>
#include<queue>
#define int long long
using namespace std;
int n,ansa,ansb;
priority_queue<int> q[3];
//q[1]:A q[0]:B
signed main()
{
scanf("%I64d",&n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%I64d",&x);
q[1].push(x);
}
for(int i=1;i<=n;i++)
{
int x;
scanf("%I64d",&x);
q[0].push(x);
}
q[1].push(-1);
q[0].push(-1);
int tot=n*2;
for(int i=1;i<=tot;i++)
{
int a=q[1].top();
int b=q[0].top();
if(i&1)//a's turn
{
if(a<b)
q[0].pop();
else
{
q[1].pop();
ansa+=a;
}
}
else//b's turn
{
if(b<a)
q[1].pop();
else
{
q[0].pop();
ansb+=b;
}
}
}
printf("%I64d",ansa-ansb);
return 0;
}