CF799E Aquarium decoration

一、题目

点此看题

二、解法

本题关键在于两个都喜欢的如何去选,既然难决策,我们就枚举,反正只有 O ( n ) O(n)

我们把所有物品分为 4 4 类,都喜欢的, A A 喜欢的, B B 喜欢的,都不喜欢的。一开始尽量选都喜欢的,使之达到 n n 个,从大到小枚举都喜欢的个数,都喜欢的减少 1 1 A A B B 如果喜欢的都不够,去掉都不喜欢的,选一个 A A 喜欢的,选一个 B B 喜欢的。

如果只有一个不够或者都够,可以写一个函数来判断,这道题比较考察实现能力。

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int M = 200005;
int read()
{
    int num=0,flag=1;
    char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
int n,m,k,t,A,B,la,lb,nr,mx,fk;
int l[4],a[M],vis[M],v[4][M];long long ans,s;
void solve(int x)
{
	while(x--)
	{
		int mi=2e9,id=-1;
		if(A<l[1] && v[1][A+1]<mi && lb>=k) mi=v[1][A+1],id=1;
		if(B<l[2] && v[2][B+1]<mi && la>=k) mi=v[2][B+1],id=2;
		if(nr<l[0] && v[0][nr+1]<mi && la>=k && lb>=k) mi=v[0][nr+1],id=3;
		if(id==-1) {fk=1;return ;}
		if(id==1) A++,la++;
		if(id==2) B++,lb++;
		if(id==3) nr++;
		s+=mi;
	}
}
signed main()
{
	n=read();m=read();k=read();
	for(int i=1;i<=n;i++) a[i]=read();
	t=read();
	for(int i=1;i<=t;i++) vis[read()]++;
	t=read();
	for(int i=1;i<=t;i++) vis[read()]+=2;
	for(int i=1;i<=n;i++)
		v[vis[i]][++l[vis[i]]]=a[i];
	for(int i=0;i<4;i++)
		sort(v[i]+1,v[i]+l[i]+1);
	if(m<k || (l[3]<k && ((k-l[3])*2+l[3]>m || k-l[3]>l[1] || k-l[3]>l[2])))
	{
		puts("-1");
		return 0;
	}
	mx=min(l[3],m);
	for(int i=1;i<=mx;i++)
		s+=v[3][i];
	la=lb=mx;
	while(A<k-l[3]) s+=v[1][++A],la++;
	while(B<k-l[3]) s+=v[2][++B],lb++;
	solve(m-mx-A-B);ans=s;
	for(int i=mx;i>=1;i--)
	{
		la--;lb--;
		s-=v[3][i];
		if(la<k && lb<k)
		{
			if(A<l[1] && B<l[2] && nr>0)
				s-=v[0][nr--],s+=v[1][++A],s+=v[2][++B],la++,lb++;//
			else break;
		}
		else solve(1);
		if(fk || la<k || lb<k) break;
		ans=min(ans,s);
	}
	printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/C202044zxy/article/details/107455683
今日推荐