题目链接: http://codeforces.com/contest/1070/problem/F
思路: 先把11的选上,然后01和10的选min(投01和10的人的个数),最后计算是否还可以再选入,然后从剩下的人当中选择影响力大的。
#include<cstdio>
#include<iostream>
#include<cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e6;
struct A
{
int a,b=0; //这里可以用int型存储,比较方便
}s10[MAXN],s01[MAXN],s00[MAXN];
bool cmp(A x,A y)
{
return x.b>y.b;
}
int main()
{
int n,ans=0;
cin>>n;
int e11=0,e10=0,e01=0,e00=0;
for(int i=0;i<n;i++)
{
int x,y;
cin>>x>>y;
if(x==11){
ans+=y;e11++; //投11的人一定会被选上,所以只需要记下影响力和人数就可以了
}
if(x==10){
s10[e10].a=x;s10[e10].b=y;e10++;
}
if(x==1){
s01[e01].a=x;s01[e01].b=y;e01++;
}
if(x==0){
s00[e00].a=x;s00[e00].b=y;e00++;
}
}
sort(s10,s10+e10,cmp); //先对s01和s10按影响力从大到小排序
sort(s01,s01+e01,cmp);
int minn=min(e01,e10);
for(int i=0;i<minn;i++)
{
ans+=s10[i].b+s01[i].b;
}
int all=(e11+minn)*2; //计算可以选上的总人数
int k=all-e11-minn*2; //k为还可以选的人数
if(e10>e01)
{
for(int i=minn;i<e10;i++) //把s01或者s10中剩余的人数加到s00中,方便排序
s00[e00++]=s10[i];
}
else
{
for(int i=minn;i<e01;i++)
s00[e00++]=s01[i];
}
sort(s00,s00+e00,cmp); //此时s00中还存有s10或s01中剩余的人,然后排序
for(int i=0;i<k;i++)
{
ans+=s00[i].b; //不需要考虑怎么投的票了,只需要选择影响力大的就可以了
}
cout<<ans<<endl;
return 0;
}