[二进制]题解 串串串

题面

你有两个长度分别为 \(n,m\) 的 01 串 \(S,T\)。 有 \(Q\) 次询问,每次询问给出 \(l_1,r_1,l_2,r_2\),其中 \(r_1−l_1+1=r_2−l_2+1\)\(a=S_{l_1 … r_1},b=T_{l_2 … r_2}\),你需要求出 \(a_i\not=b_i\) 的位置个数对 \(2\) 取模的结果

思路

显然 \(a_i \not= b_i\) 就是 \(xor\) 运算的值,答案就是要求

\[\sum a_i\ \ xor\ \ b_i \]

的奇偶性。

注意到由于 \(xor\) 本身的操作就有一种自带的奇偶性存在。

\[\boxed{\begin{cases}a \quad xor \quad b \in E \\ c\quad xor \quad d \in E \\ e \quad xor \quad f \in O\end{cases}} \]

\(E\) 为偶数集,\(O\) 为奇数集。 并且 \(a\in E,b\in E,c\in O,d\in O,e\in O,f\in E\)

答案其实就是求 \((a_i \ \ xor \ \ b_i)\quad xor\quad (a_{i+1}\quad xor\quad b_{i+1})\quad xor ...\)
观察到由于 \(xor\) 运算可以拆括号,也有交换律。
所以答案转化成 \((a_i\ xor\ a_{i+1}\ xor\ a_{i+2}\ xor ...) \quad xor\quad (b_i\ xor\ b_{i+1}\ xor\ b_{i+2}\ xor ...)\)

对于 \((a_i\ xor\ a_{i+1}\ xor\ a_{i+2}\ xor ...)\) 利用一种类似于前缀和的思想,那么对于一段 \(a_{l}\)\(a_{r}\) 用前缀和思想加减就好了。至于为什么可以这样做,因为答案要求的是奇偶,而加法运算是最显然有奇偶性的一个了。

#include <bits/stdc++.h>
#define debug puts("I ak IOI several times");
#define pb push_back
using namespace std;
template <typename T>inline void read(T& t){
    t=0; register char ch=getchar(); register int fflag=1;
    while(!('0'<=ch&&ch<='9')){if(ch=='-') fflag=-1;ch=getchar();}
    while(('0'<=ch&&ch<='9')){t=((t<<1)+(t<<3))+ch-'0'; ch=getchar();} t*=fflag;
}
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) putchar('-'),x=~(x-1); int s[40],top=0;
    while(x) s[++top]=x%10,x/=10; if(!top) s[++top]=0;
    while(top) putchar(s[top--]+'0');
}
inline bool Get(){
	char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	return (ch-48);
}
const int MAXN=200086;
int n,m;
bitset<MAXN>a,b,c,d;
int main(){
	//freopen("string2.in","r",stdin);
	//freopen("string2.out","w",stdout);
	read(n,m);
	for(int i=1;i<=n;++i) a[i]=Get();
	for(int i=1;i<=m;++i) b[i]=Get();
	c[1]=d[1]=0;
	for(int i=2;i<=n;++i) c[i]=a[i]^c[i-1];
	for(int i=2;i<=m;++i) d[i]=b[i]^d[i-1];
	/*for(int i=1;i<=n;++i) cout<<c[i];
	cout<<endl;
	for(int i=1;i<=m;++i) cout<<d[i];*/
	int Q; read(Q);
	while(Q--){
		register int l,r,ll,rr,res=0;
		read(l,r,ll,rr);
		write((c[r]-c[l-1]+d[rr]-d[ll-1]+2)%2);
		putchar('\n');
		/*
		for(register int i=l,j=ll;i<=r,j<=rr;++i,++j) res=res+(a[i]^b[j]);
		write(res%2),puts("");*/
	}
    return 0;
}
//Welcome back,Chtholly.
posted @ 2022-01-07 14:25  Mercury_City  阅读(83)  评论(0编辑  收藏  举报