题意:n个人,每个人是4种类型的其中一种(00,10,01,11) 不支持A,B.只支持A,只支持B,AB都支持.
第i个人的权值为a[i], 要求从n个人中选出一个子集.(假设选出的人数为m)
条件1:支持A的人数 2*a>=m.
条件2:支持B的人数 2*b>=m.
n<=4e5. 1<=a[i]<=5000. 问满足条件时,最大的权值和为多少?
假设选出两个满足条件的不相交集合S1,S2. 则合并S1,S2以后也是一个合法解(2*x1>=m,2*x2>=m2,-> 2(x1+x2)>=m1+m2).
令集合1只选10,01 显然10,01的个数只能相同. 权值尽量大则能选多少选多少.
令集合2只选11,00 显然00的个数不能超过11.先把11全部选上后(y个11),在枚举00的个数(x个00).
现在合并集合1和集合2. 在从(10,01)剩下的序列中选(y-x)个即可.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
const int N=4e5+5;
string s;
int x,suf[N],n,m;
vector<int> v[N];
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin>>n;
int res=0;
for(int i=0;i<n;i++){
cin>>s>>x;
int tp=3;
if(s=="00") tp=0;
if(s=="10") tp=1;
if(s=="01") tp=2;
if(s=="11"){
m++;
res+=x;
}
v[tp].push_back(x);
}
for(int i=0;i<4;i++){
sort(v[i].begin(),v[i].end());
reverse(v[i].begin(),v[i].end());
}
if(v[1].size()<v[2].size())swap(v[1],v[2]);
for(int i=0;i<v[2].size();i++) res+=v[2][i],res+=v[1][i];
for(int i=v[1].size()-1;i>=0;i--) suf[i]=suf[i+1]+v[1][i];
int p1=v[2].size(),sum=res;
res=max(res,sum+suf[p1]-suf[p1+m]);
for(int i=0;i<min(int(v[0].size()),m);i++){
sum+=v[0][i];
int can=m-(i+1);
sum+=suf[p1]-suf[p1+can];
res=max(res,sum);
sum=sum-(suf[p1]-suf[p1+can]);
}
cout<<res<<'\n';
return 0;
}