D - Even-Odd Game
CodeForces - 1472D
题目大意
有一堆数,两个小孩比赛,小孩A先开始选择某个数,如果是偶数,小孩A加上相应得分,如果是奇数,不加分。然后小孩B在接下来得数中选择某个数,如果是奇数,小孩B加上相应的分,如果是偶数,不加分。
最后比较两个小孩的分数(假设两个人都发挥最佳),如果分数相等输出“tie”,否则输出赢得人的名字。
思路
(这道题是我第一次完整的用优先队列做的ac题,超开心~~)
首先为什么会想到用优先队列 。
这里补充下优先队列的性质,优先队列是有顺序的数列(默认是从大到小) 正好符合本题发挥最佳的要求,其次,优先队列有pop(),可以及时把用过的数pop()掉,十分方便间接。
下面说下这道题的具体思路
首先需要把奇数和偶数分开(这是因为小孩A可以选给自己加分的偶数,也可以选较大的奇数,从而使小孩B选不到较大的奇数,是自己有更大的赢的可能)这里要理解一下
因为要把奇数和偶数分开,所以要定义两个优先队列变量,分别存储奇数和偶数。(这里由于优先队列的功能,放进去的数已经排好了顺序从大到小)。然后分别取出两个队列的头进行比较,如果偶数大于奇数,那么小孩A可以选择偶数使自己获得更多的分,相反如果奇数大于偶数,那么小孩A应该选择奇数来组织小孩B得到更大的奇数。最后分别记录小孩A和小孩B的总分进行比较,结果就出来啦!!!
代码如下
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
priority_queue<int >J,O;
const int N=2e5+5;
int a[N];
int main()
{
int t,n;
cin >> t;
while (t--)
{
cin >> n;
for (int i=1; i<=n; i++)
{
cin >> a[i];
}
while(J.size())J.pop();
while(O.size())O.pop();
int j=1,g=1;
for(int i=1; i<=n; i++)
{
if(a[i]%2==0) {O.push(a[i]);}
if(a[i]%2!=0) {J.push(a[i]);}
}
ll x=0,y=0;int a,b;
while(J.size()||O.size())
{
if (O.size()!=0)a=O.top();
else a=0;
if (J.size()!=0)b=J.top();
else b=0;
if(a>=b){
x=x+a;
O.pop();}
else J.pop();
if (O.size()!=0){a=O.top();}
else a=0;
if (J.size()!=0){b=J.top();}
else b=0;
if(O.size()==0&&J.size()==0)break;
if(a<=b){
y=y+b;
J.pop();}
else O.pop();
}
if (x==y){cout << "Tie\n";}
if (x-y> 0){cout << "Alice\n";}
if(x<y){cout << "Bob\n";}
}
}
题目链接
https://vjudge.net/problem/CodeForces-1472D/origin
可以复制去看哦~