NEERC-SSC F Debate 思维

题意: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;
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值