CF1392G Omkar and Pies状压DP

Posted cjTQX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1392G Omkar and Pies状压DP相关的知识,希望对你有一定的参考价值。

CF1392G Omkar and Pies

Description

给定两个长度为 \\(k\\)\\(01\\) 串,分别是起始串和目标串。

依次给出 \\(n\\) 个可选操作,第 \\(j\\) 个操作 \\(a_j,b_j\\) 表示交换起始串的 \\(a_j\\) 位置与 \\(b_j\\) 位置。

你需要选择操作序列中其中连续的一段操作依次按顺序执行,并且选择的操作数量不小于 \\(m\\)

你需要让操作完成后的串与目标串对应相同的位置数量尽可能多。

输出最大数量与你选取操作的区间(若有多种方案输出任意一个即可)。

\\(k\\le 20,m\\le n\\le 10^6\\)

Solution

首先执行 \\([l,r]\\) 的区间操作可以转化为,对起始串进行 \\([l,n]\\) 操作,再对目标串进行 \\([r+1,n]\\) 操作,这样一来 \\([r+1,n]\\) 的操作相当于被抵消了,就跟原问题一样了。

首先可以 \\(\\mathcal O(nk)\\) 预处理出对起始串与目标串执行所有后缀操作得到的序列,设分别为 \\(\\{a_n\\}\\)\\(\\{b_n\\}\\)

现在我们等于需要最大化 \\(a_i\\)\\(b_j\\) 的相同字符数量,并使 \\(j-i\\ge m\\),设 \\(x\\)\\(a_i\\)\\(1\\) 的个数,\\(y\\)\\(b_j\\)\\(1\\) 的个数,\\(z\\)\\(a_i\\)\\(b_j\\) 同时为 \\(1\\) 的位置数量,因此对应相同的位置数量就等于:

\\[z+(k-x-y+z)=2z+k-x-y \\]

由于 \\(x,y\\) 是确定的,因此只需要最大化 \\(z\\)。枚举最终公共 \\(1\\) 的位置为 \\(s\\),求出:

\\[dp_{0,s}=\\min i[s\\subset a_i]\\\\ dp_{1,s}=\\max i[s\\subset b_i] \\]

如果 \\(dp_{1,s}-dp_{0,s}\\ge m\\) ,就可以用 \\(popcount(s)\\) 来更新答案了,于是预处理 \\(a,b,dp\\) 的复杂度都是 \\(\\mathcal O(nk)\\)。总复杂度为 \\(\\mathcal O(nk)\\),可以通过此题。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=(1<<20)+20;
int n,m,k,a,b,L[N],R[N],c[N],f[N],g[N],tmp[N][21],ret[21];
char s[21],t[21];
int main(){
//	freopen("option2.in","r",stdin);
	scanf("%d%d%d",&n,&m,&k);
	scanf("%s",s+1);
	int cta=0,ctb=0;
	for(int i=1;i<=k;++i){
		a=(a<<1)+s[i]-\'0\';
		if(s[i]==\'1\') cta++;
	}
	scanf("%s",t+1);
	for(int i=1;i<=k;++i){
		b=(b<<1)+t[i]-\'0\';
		if(t[i]==\'1\') ctb++;
	}
	for(int i=0;i<(1<<k);++i) f[i]=n+1,g[i]=0;
	for(int i=1;i<=n;++i) scanf("%d%d",&L[i],&R[i]);
	for(int i=1;i<=k;++i) ret[i]=i;
	for(int i=n;i>=1;--i){
		for(int j=1;j<=k;++j) tmp[i][j]=j;
		swap(tmp[i][L[i]],tmp[i][R[i]]);
		for(int j=1;j<=k;++j) ret[j]=tmp[i][ret[j]];
		a=0;
		for(int j=1;j<=k;++j) a=(a<<1)+s[ret[j]]-\'0\';
		f[a]=min(f[a],i);
	}
	g[b]=n+1;
	for(int i=1;i<=k;++i) ret[i]=i;
	for(int i=n;i>=1;--i){
		for(int j=1;j<=k;++j) tmp[i][j]=j;
		swap(tmp[i][L[i]],tmp[i][R[i]]);
		for(int j=1;j<=k;++j) ret[j]=tmp[i][ret[j]];
		b=0;
		for(int j=1;j<=k;++j) b=(b<<1)+t[ret[j]]-\'0\';
		g[b]=max(g[b],i);
	}
	int ans=-1,reta=0,retb=0;
	for(int i=((1<<k)-1);~i;--i){
		int ct=0;
		for(int j=0;j<k;++j){
			if(i&(1<<j)){
				ct++;
				int tmp=i^(1<<j);
				f[tmp]=min(f[tmp],f[i]);
				g[tmp]=max(g[tmp],g[i]);
			}
		}
		if(g[i]-f[i]>=m){
			int ret=k-cta-ctb+ct+ct;
			if(ret>ans) ans=ret,reta=f[i],retb=g[i]-1;
		}
	}
	printf("%d\\n%d %d",ans,reta,retb);
	return 0;
}

以上是关于CF1392G Omkar and Pies状压DP的主要内容,如果未能解决你的问题,请参考以下文章

D - Omkar and Medians(数据结构+思维)

CF580D Kefa and Dishes 状压dp

CodeforcesRound#749(Div.1.2basedonTechnocup2022EliminationRound1)-D.Omkar and the Meaning of Life-题解

Codeforces Round #724 (Div. 2) D .Omkar and Medians(中位数,构造)

CF580D Kefa and Dishes 状压dpBy cellur925

CF449D Jzzhu and Numbers (状压DP+容斥)