【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;
}