洛谷 P5470 - [NOI2019] 序列(反悔贪心)

洛谷题面传送门

好几天没写题解了,写篇题解意思一下(大雾

考虑反悔贪心,首先我们考虑取出 \(a,b\) 序列中最大的 \(k\) 个数,但这样并不一定满足交集 \(\ge L\) 的限制,因此我们需要调整,我们假设 \(L-\) \(a,b\) 序列中最大的 \(k\) 个数的交集为 \(L'\),如果 \(L'\le 0\) 那不用调整直接输出即可。否则我们考虑每次调整部分 \(a_i,b_i\) 的取值使得 \(a,b\) 的交集加 \(1\),不难发现每次调整可能有以下可能:

  1. 选择两个下标 \(x,y\),满足选择了 \(a_x\) 没选 \(b_x\),以及选择了 \(b_y\) 没选 \(a_y\),将 \(a_x\) 改为 \(a_y\),答案增加 \(a_y-a_x\)
  2. 选择两个下标 \(x,y\),满足选择了 \(b_x\) 没选 \(a_x\),以及选择了 \(a_y\) 没选 \(b_y\),将 \(b_x\) 改为 \(b_y\),答案增加 \(b_y-b_x\)
  3. 选择三个下标 \(x,y,z\),满足选择了 \(a_x\) 没选 \(b_x\),选择了 \(b_y\) 没选 \(a_y\)\(a_z,b_z\) 都没选,将 \(a_x\) 改为 \(a_z\)\(b_y\) 改为 \(a_z\),答案增加 \((a_z+b_z)-a_x-b_y\)
  4. 选择三个下标 \(x,y,z\),满足选择了 \(a_x\) 没选 \(b_x\),选择了 \(b_y\) 没选 \(a_y\)\(a_z,b_z\) 都被选择了,将 \(a_z\) 改为 \(a_y\)\(b_z\) 改为 \(b_x\),答案增加 \(a_y+b_x-(a_z+b_z)\)

思路理到这里,聪明的读者一定能够发现,接下来的步骤与此题第二个解法大同小异了,我们记 \(st_i\) 表示下标为 \(i\) 的位置被选择的情况,\(st_i=0\) 表示 \(a_i,b_i\) 都没选,\(st_i=1\) 表示 \(a_i\) 被选 \(b_i\) 没选,\(st_i=2\) 表示 \(b_i\) 被选 \(a_i\) 没选,\(st_i=3\) 表示 \(a_i,b_i\) 都被选。

那么考虑维护六个大根堆:

  • \(q_1=\{a_i|st_i=2\}\)
  • \(q_2=\{b_i|st_i=1\}\)
  • \(q_3=\{-a_i|st_i=1\}\)
  • \(q_4=\{-b_i|st_i=2\}\)
  • \(q_5=\{a_i+b_i|st_i=0\}\)
  • \(q_6=\{-a_i-b_i|st_i=3\}\)

对于情况 \(1\) 相当于是取出 \(q_1,q_3\) 的根节点,情况 \(2\) 相当于是取出 \(q_2,q_4\) 的根节点,情况 \(3\) 相当于是取出 \(q_3,q_4,q_5\) 的根节点,情况 \(4\) 相当于是取出 \(q_1,q_2,q_6\) 的根节点,然后 xjb 乱搞一下就行了(确信

时间复杂度线对。

感觉这个 D1T3 比 D1T2 简单,虽然我都不会做

const int MAXN=2e5;
int n,k,l,a[MAXN+5],b[MAXN+5],st[MAXN+5];
pii ap[MAXN+5],bp[MAXN+5]; 
priority_queue<pii> q1,q2,q3,q4,q5,q6;
/*
q1: maximum a[i] with st[i]=2
q2: maximum b[i] with st[i]=1
q3: maximum -a[i] with st[i]=1
q4: maximum -b[i] with st[i]=2
q5: maximum a[i]+b[i] with st[i]=0
q6: maximum -a[i]-b[i] with st[i]=3
*/
void solve(){
	scanf("%d%d%d",&n,&k,&l);memset(st,0,sizeof(st));
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),ap[i]=mp(a[i],i);
	for(int i=1;i<=n;i++) scanf("%d",&b[i]),bp[i]=mp(b[i],i);
	sort(ap+1,ap+n+1);reverse(ap+1,ap+n+1);
	sort(bp+1,bp+n+1);reverse(bp+1,bp+n+1);ll ans=0;
	for(int i=1;i<=k;i++) st[ap[i].se]|=1,ans+=ap[i].fi;
	for(int i=1;i<=k;i++) st[bp[i].se]|=2,ans+=bp[i].fi;
	for(int i=1;i<=n;i++) l-=(st[i]==3);chkmax(l,0);
	q1.push(mp(-2e9,0));q2.push(mp(-2e9,0));q3.push(mp(-2e9,0));
	q4.push(mp(-2e9,0));q5.push(mp(-2e9,0));q6.push(mp(-2e9,0));
	for(int i=1;i<=n;i++){
		if(st[i]==2){
			q1.push(mp(a[i],i));
			q4.push(mp(-b[i],i));
		} if(st[i]==1){
			q2.push(mp(b[i],i));
			q3.push(mp(-a[i],i));
		} if(!st[i]){
			q5.push(mp(a[i]+b[i],i));
		} if(st[i]==3){
			q6.push(mp(-a[i]-b[i],i));
		}
	}
	while(l--){
		#define qpop(a,b)\
			while(!q##a.empty()){\
				int x=q##a.top().se;\
				if(!x||st[x]==b) break;\
				q##a.pop();\
			}
		qpop(1,2);qpop(2,1);qpop(3,1);
		qpop(4,2);qpop(5,0);qpop(6,3);
		ll res1=0ll+q1.top().fi+q3.top().fi;
		ll res2=0ll+q2.top().fi+q4.top().fi;
		ll res3=0ll+q3.top().fi+q4.top().fi+q5.top().fi;
		ll res4=0ll+q1.top().fi+q2.top().fi+q6.top().fi;
		ll mx=max(max(res1,res2),max(res3,res4));ans+=mx;
		if(res1==mx){
			int x=q1.top().se,y=q3.top().se;
			q1.pop();q3.pop();st[x]=3;st[y]=0;
			q5.push(mp(a[y]+b[y],y));
			q6.push(mp(-a[x]-b[x],x));
		} else if(res2==mx){
			int x=q2.top().se,y=q4.top().se;
			q2.pop();q4.pop();st[x]=3;st[y]=0;
			q5.push(mp(a[y]+b[y],y));
			q6.push(mp(-a[x]-b[x],x));
		} else if(res3==mx){
			int x=q3.top().se,y=q4.top().se,z=q5.top().se;
			q3.pop();q4.pop();q5.pop();st[x]=st[y]=0;st[z]=3;
			q5.push(mp(a[x]+b[x],x));
			q5.push(mp(a[y]+b[y],y));
			q6.push(mp(-a[z]-b[z],z));
		} else{
			int x=q1.top().se,y=q2.top().se,z=q6.top().se;
			q1.pop();q2.pop();q6.pop();st[x]=st[y]=3;st[z]=0;
			q6.push(mp(-a[x]-b[x],x));
			q6.push(mp(-a[y]-b[y],y));
			q5.push(mp(a[z]+b[z],z));
		}
	} printf("%lld\n",ans);
	#define clr(x) while(!q##x.empty()) q##x.pop();
	clr(1);clr(2);clr(3);clr(4);clr(5);clr(6);
}
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	int qu;scanf("%d",&qu);
	while(qu--) solve();
	return 0;
}
posted @ 2021-07-22 09:04  tzc_wk  阅读(67)  评论(0)    收藏  举报