【SSLOJ1477】赛

题目

思路

重题 : CF1374E2
将物品分成两人都喜欢、第一人喜欢、第二人喜欢、没人喜欢四类,枚举两人都喜欢的物品选取 \(i\) 个,然后将一人喜欢的物品前 \(k-i\) 个取出,这样我们就保证了每个人至少有喜欢的 \(k\) 个物品。
然后将剩余的物品加入对顶堆中,求前 \(m-i-2k\) 的和即可。
时间复杂度 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=200010;
int n,m,k,s0,s1,s2,a[3][N],b[N];
ll sum,sum1,sum2,sum0,ans;
bool like[2][N];
priority_queue<int> q1,q2;

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=n;i++)
		scanf("%d",&b[i]);
	scanf("%d",&s1);
	for (int i=1,x;i<=s1;i++)
	{
		scanf("%d",&x);
		like[0][x]=1;
	}
	scanf("%d",&s2);
	for (int i=1,x;i<=s2;i++)
	{
		scanf("%d",&x);
		like[1][x]=1;
	}
	s1=s2=0;
	for (int i=1;i<=n;i++)
	{
		if (like[0][i] && like[1][i]) a[0][++s0]=b[i];
		else if (like[0][i]) a[1][++s1]=b[i],sum1+=b[i];
		else if (like[1][i]) a[2][++s2]=b[i],sum2+=b[i];
		else q2.push(-b[i]);
	}
	sort(a[0]+1,a[0]+1+s0); sort(a[1]+1,a[1]+1+s1); sort(a[2]+1,a[2]+1+s2);
	ans=1000000000000000000LL;
	for (int i=0,p1=s1,p2=s2;i<=min(s0,k);i++)
	{
		sum0+=a[0][i];
		int p=k-i;
		if (s1<p || s2<p) continue;
		for (;p1>p;p1--) q2.push(-a[1][p1]),sum1-=a[1][p1];
		for (;p2>p;p2--) q2.push(-a[2][p2]),sum2-=a[2][p2];
		while (q2.size() && (int)q1.size()<m-i-p-p)
		{
			sum+=-q2.top();
			q1.push(-q2.top()); q2.pop();
		}
		if (q1.size()==m-i-p-p)
			ans=min(ans,sum1+sum2+sum0+sum);
	}
	if (ans==1000000000000000000LL) printf("-1");
		else printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/13507400.html