CF1250I Show Must Go On

时间:2021-08-07
本文章向大家介绍CF1250I Show Must Go On,主要包括CF1250I Show Must Go On使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

CF1250I Show Must Go On

发现此题网上没有题解,赶紧写一发,可能增加知名度

先翻译一下题面,主要是因为原文太有文采(离谱)
给定一个可重集,在其所有和小于\(k\)的子集中,按照子集大小为第一关键字降序排序,子集和为第二关键字升序排序,输出前\(m\)个子集的大小和和,若满足条件的自己不足\(m\)个,则全输出。对于最后一个子集,还要输出子集内元素的下标。
语文能力有限,尽力了

首先考虑第一关键字的问题
子集的\(size\)是一个很刁钻的条件,比较难动态进行维护,否则肯定要记录大量无用状态
所以考虑枚举\(size\),即强制\(size\)大小。
我们可以将每种方案视为由最小的方案置换了一些数的过程,而且为了使得子集的和慢慢递增,由一个数只会置换成与其相邻的一个数
想到这个结论,我们敏锐的感觉到对于一个状态的描述应该是突破口。
我们不妨强制每个数都是有序的,即在最初方案中第\(k\)大的数在最终方案中也是第\(k\)
于是我们可以先决策完大数,在决策小数,这样对于状态的描述就非常简单了,只需要记录和,当前决策第k大的数,第k大的数最大能为多少(由于第\(k\)大的数不能大于第\(k-1\)大的数),这样同时解决了答案去重的问题。
然后由于取前\(m\)个子集,可以用堆维护上述决策过程。对于输出最后一个子集,只要在决策时记录路径即可。

于是得到了代码:
(等等,下面还有一种解法)

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

#define Mod(x) ((x>=P)&&(x-=P))||((x<0)&&(x+=P))
#define rep(i,a,b) for(ll i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(ll i=a,i##end=b;i>=i##end;--i)
#define erep(i,a,b) for(ll i=hd[a];i;i=nxt[i])
#define debug(x) cerr<<#x<<":"<<x<<endl

typedef long long ll;
void Max(ll &x,ll y){x<y&&(x=y);}
void Min(ll &x,ll y){x>y&&(x=y);}

bool vio;
char IO;
ll rd(ll res=0){
	bool f=0;
	while(IO=getchar(),IO<48||IO>57)
		f|=IO=='-';
	do res=(res<<1)+(res<<3)+(IO^48);
	while(IO=getchar(),isdigit(IO));
	return f?-res:res;
}
const ll M=1e6+10;
struct node{
	ll sum,x,bt,r,pre,id;
	bool operator <(const node &_)const{
		return sum>_.sum;
	}
};
ll A[M],id[M],s[M];
bool cmp(ll a,ll b){return A[a]<A[b];}
struct ANS{ll x,val,i,pre,bt;}ans[M];
priority_queue<node>que;
bool let;
int main() {
	cerr<<(&vio-&let)/1024.0/1024<<endl;
	rep(cas,1,rd()){
		while(!que.empty())que.pop();
		ll n=rd(),q=rd(),m=rd();
		rep(i,1,n)A[i]=rd(),id[i]=i;
		sort(id+1,id+n+1,cmp);
		sort(A+1,A+n+1);
		ll st=0,tot=0;
		rep(i,1,n){
			s[i]=s[i-1]+A[i];
			if(s[i]<=q)st=i;
		}
		drep(k,st,1){
			que.push((node){s[k],k,k,n,0,0});
			while(!que.empty()&&tot<m){
				node tmp=que.top();que.pop();
				ll sum=tmp.sum,x=tmp.x,bt=tmp.bt;
				ll r=tmp.r,pre=tmp.pre,id=tmp.id;
				if(!id){
					id=++tot;
					ans[tot]=(ANS){k,sum,x,pre,bt};
				}
				if(x<r&&sum-A[x]+A[x+1]<=q)que.push((node){sum-A[x]+A[x+1],x+1,bt,r,tmp.pre,0});
				if(bt>1&&x!=bt)que.push((node){sum,bt-1,bt-1,x-1,id,id});
			}
			if(tot==m)break;
		}
		printf("%lld\n",tot);
		if(tot){
			rep(i,1,tot)printf("%lld %lld\n",ans[i].x,ans[i].val);
			ll t=tot;
			rep(i,1,ans[t].bt-1)printf("%lld ",id[i]);
			while(ans[t].i){
				printf("%lld ",id[ans[t].i]);
				t=ans[t].pre;	
			}
			puts("");
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Saltywater/p/15111228.html