题解 CF1392G Omkar and Pies

link

Solution

可以想到的是,如果我们选了区间 \([L,R]\),那么相当于我们对 \(s\) 进行 \([L,n]\) 的操作,对 \(t\) 进行 \([R+1,n]\) 的操作(注意一定得是后缀,因为前缀换是前面的)。

那么我们就可以对于每一个后缀都求出 \(s,t\) 的变化情况,然后直接枚举两者交集的 \(1\) 个数即可。因为答案只跟交集中 \(1\) 的个数有关。

复杂度 \(\Theta(nk+k2^k)\) 。

Code

#include <bits/stdc++.h>
using namespace std;
 
#define Int register int
#define MAXM 1000005
#define MAXN 25
 
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
 
int n,m,k,tx[MAXM],ty[MAXM],s1[MAXN],s2[MAXN],sa[MAXN],sb[MAXN],Sa[1 << 20],Sb[1 << 20],siz[1 << 20],tmpa[MAXN],tmpb[MAXN];
 
void putout (int S){
	for (Int i = 0;i < k;++ i) cout << (S >> i & 1);
}
 
struct node{
	int pos[MAXN];
	node operator + (const node &p)const{
		node New;
		for (Int i = 1;i <= k;++ i) New.pos[i] = p.pos[pos[i]];
		return New;
	}
};
 
signed main(){
	read (n,m,k);int p = 0,q = 0;
	for (Int i = 1;i <= k;++ i) scanf ("%1d",&s1[i]),sa[i] = s1[i],p += s1[i];
	for (Int i = 1;i <= k;++ i) scanf ("%1d",&s2[i]),sb[i] = s2[i],q += s2[i];
	for (Int i = 1;i <= n;++ i) read (tx[i],ty[i]);memset (Sa,0x3f,sizeof (Sa));
	node fuc;
	for (Int i = 1;i <= k;++ i) fuc.pos[i] = i;
	for (Int i = n + 1;i >= 1;-- i){
		node f;
		for (Int h = 1;h <= k;++ h) f.pos[h] = h;
		swap (f.pos[tx[i]],f.pos[ty[i]]),fuc = f + fuc;
		int ta = 0,tb = 0;
		for (Int h = 1;h <= k;++ h) tmpa[fuc.pos[h]] = sa[h],tmpb[fuc.pos[h]] = sb[h];
		for (Int h = k;h >= 1;-- h) ta = ta << 1 | tmpa[h],tb = tb << 1 | tmpb[h];
		chkmin (Sa[ta],i),chkmax (Sb[tb],i);
	}
	for (Int i = 0;i < k;++ i)
		for (Int s = (1 << k) - 1;~s;-- s) if (!(s >> i & 1)) chkmin (Sa[s],Sa[s + (1 << i)]),chkmax (Sb[s],Sb[s + (1 << i)]);
	int ans = 0;
	for (Int s = 0;s < (1 << k);++ s) siz[s] = siz[s >> 1] + (s & 1);
	for (Int s = 0;s < (1 << k);++ s) if (Sb[s] - Sa[s] >= m && siz[s] > siz[ans]) ans = s;
	write (siz[ans] * 2 + k - p - q),putchar ('\n');
	write (Sa[ans]),putchar (' '),write (Sb[ans] - 1),putchar ('\n'); 
	return 0;
}
上一篇:【函数学习笔记】编写函数输出一个十进制整数的十六进制形式


下一篇:MySQL有哪些存储引擎,各自的优缺点,应用场景