题解 CF1183G 【Candy Box (hard version)】
感觉D题的思路对G题有一定的提示作用。
首先对于每一个种类记录一个
我们考虑D题的思路:将所有的
放到这道题上,为了选出来最优答案,我们还是需要将所有
怎么办呢?容易发现答案可以拆成若干个互不相同的数相加(就是贪心的过程中每一个种类的糖果选取的数量),那么我们可以想到,对于一个数
接下来我们的问题就是对每一个
所以对于一个数
这样做一定是最优的,证明如下:
考虑最优答案,我们发现如果最优答案下
如果
最后我们需要实现一个数据结构,支持插入和查询最大值,用一个堆就可以了。
时间复杂度
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int t,n,cnt0[200005],cnt1[200005],sa[200005];
priority_queue<int>q;
bool cmp(int a,int b)
{
return cnt0[a]+cnt1[a]>cnt0[b]+cnt1[b];
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(y)cnt0[x]++;
else cnt1[x]++;
sa[i]=i;
}
while(!q.empty())q.pop();
sort(sa+1,sa+n+1,cmp);
int now=1,ans=0,num=0;
for(int i=n;i>=1;i--)
{
while(cnt0[sa[now]]+cnt1[sa[now]]>=i)
{
q.push(cnt0[sa[now]]);
now++;
}
if(q.empty())continue;
int v=q.top();
q.pop();
ans+=i;
num+=min(v,i);
}
printf("%d %d\n",ans,num);
for(int i=1;i<=n;i++)cnt0[i]=cnt1[i]=0;
}
return 0;
}