[BZOJ5301][莫队]CQOI2018异或序列

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/87875148

BZOJ5301

s u m [ i ] [ j ] sum[i][j] 表示 i j i-j 异或起来的值
异或有性质: s u m [ 1 ] [ x ] x o r s u m [ 1 ] [ y ] = s u m [ x ] [ y ] sum[1][x] xor sum[1][y] = sum[x][y] 证明就是异或可以相互抵消
(树上也有类似的性质, s u m [ r o o t ] [ x ] x o r s u m [ r o o t ] [ y ] = s u m [ x ] [ y ] sum[root][x] xor sum[root][y] = sum[x][y]
然后不就变成莫队模板题了(CQOI2018都是些什么东西,考了模板X3)

位运算打括号

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=1e5+5;
int n,m,k,sqr;
int a[N],sum[N],ans[N],tot,cnt[N];
struct Q{int l,r,id,bel;}q[N];
inline bool cmp(Q a,Q b){
	if(a.bel==b.bel) return a.r<b.r;
	return a.bel<b.bel;
}
int main(){
	n=read();m=read();k=read(),sqr=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=m;i++){
		q[i].l=read(),q[i].r=read();
		q[i].id=i;q[i].bel=(q[i].l-1)/sqr+1;
	}
	sum[1]=a[1];
	for(int i=2;i<=n;i++) sum[i]=sum[i-1]^a[i];
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	for(int i=1;i<=m;i++){
		while(r<q[i].r){
			cnt[sum[++r]]++,tot+=cnt[sum[r]^k];
			if((sum[r]^k)==sum[l-1]) ++tot;
		}
		while(r>q[i].r){
			tot-=cnt[sum[r]^k],cnt[sum[r]]--;
			if((sum[r--]^k)==sum[l-1]) --tot;
		}
		while(l<q[i].l) tot-=cnt[sum[l-1]^k],cnt[sum[l++]]--;
		while(l>q[i].l) cnt[sum[--l]]++,tot+=cnt[sum[l-1]^k];
		ans[q[i].id]=tot;
	}
	for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/87875148