题解 辩论
题目描述
具体做法与心路历程
看到这道题我秒想了网络流
,搞了下没出来,发现是个简单的贪心,不难想。
具体做法
设 A , B A,B A,B表示支持议题 1 1 1的人数和支持议题 2 2 2的人数,没选一个就把对应的 + 1 , − 1 +1,-1 +1,−1
- 如果态度为 11 11 11,那么可以贪心的全选了。
- 如果 A , B > 0 A,B>0 A,B>0,那么 01 , 10 01,10 01,10各选一个后 A , B A,B A,B不变,所以每次贪心选最大的 01 , 10 01,10 01,10各一个。
- 当 10 , 01 10,01 10,01某个不够时,相当于最多只能再选 m i n ( A , B ) min(A,B) min(A,B)个了,贪心在剩下的选最大即可
C o d e \mathcal{Code} Code
/*******************************
Author:galaxy yr
LANG:C++
Created Time:2019年10月24日 星期四 08时07分28秒
*******************************/
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct IO{
template<typename T>
IO & operator>>(T&res)
{
T q=1;char ch;
while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
res=(ch^48);
while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
res*=q;
return *this;
}
}cin;
int n,a,A,B;
long long ans;
priority_queue<int>X,Y,Z;
//(-1,-1),(1,-1),(-1,1)
bool check()
{
if(!A && !B) return false;
if(X.empty() && Y.empty() && Z.empty())
return false;
if(Y.empty() && !A)
return false;
if(Z.empty() && !B)
return false;
return true;
}
void solve()
{
if(!A)
{
ans+=Y.top();
Y.pop();
A++,B--;
return;
}
if(!B)
{
ans+=Z.top();
Z.pop();
A--,B++;
return;
}
if(A>0 && B>0 && !Y.empty() && !Z.empty())
{
ans+=Y.top()+Z.top();
Y.pop(),Z.pop();
return;
}
A--,B--;
if(Y.empty() && Z.empty())
{
ans+=X.top(),X.pop();
return;
}
if(Y.empty())
{
if(X.empty() || X.top()<Z.top())
ans+=Z.top(),Z.pop();
else
ans+=X.top(),X.pop();
return;
}
if(Z.empty())
{
if(X.empty() || X.top()<Y.top())
ans+=Y.top(),Y.pop();
else
ans+=X.top(),X.pop();
return;
}
}
int main()
{
//freopen("debate.in","r",stdin);
//freopen("debate.out","w",stdout);
cin>>n;
int ch;
for(int i=1;i<=n;i++)
{
cin>>ch>>a;
if(ch==11)
A++,B++,ans+=a;
if(ch==0)
X.push(a);
if(ch==10)
Y.push(a);
if(ch==1)
Z.push(a);
}
while(true)
{
if(!check())break;
solve();
}
printf("%lld\n",ans);
return 0;
}