Codeforces Round #340 (Div. 2) E. XOR and Favorite Number (莫队裸题)

/**
链接:https://codeforces.com/contest/617/problem/E
题意:区间异或值为k的不同的区间的个数
sum[i]:a[1]^a[2]^a[3]^....^a[i]  表示 前缀异或和

存在a[l]^a[l+1]^a[l+2]^.....a[r]=sum[l-1]^sum[r];
因此找这样的一个区间的话  由于区间是连续的(废话)

如果sum[l-1]^sum[r]=k,那么就有sum[l-1]^k=sum[r];
通过这样的性质  窝们就可以找出所在区间满足条件的个数
因此窝们需要一个数组cnt来记录
sum[r] 或者  sum[l-1]出现的次数; 也就是不同数字出现的次数;
*/


#include<bits/stdc++.h>
#define ll long long
using namespace std;

/**********************************************Head-----Template****************************************/
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){ll gg=gcd(a,b);a/=gg;if(a<=LLONG_MAX/b) return a*b;return LLONG_MAX;}
/********************************Head----Temlate**********************************************/


const int maxn=2e6+7;

struct node {
	int l,r,id;
}a[maxn];

ll val[maxn];
ll cnt[maxn];
int pos[maxn],s[maxn];

bool cmp(node a,node b){
	if(pos[a.l]==pos[b.l]) return a.r<b.r;
	return pos[a.l]<pos[b.l];
}

ll ans=0;
int n,m,k;
void add(int x){
	ans+=cnt[s[x]^k];
	cnt[s[x]]++;
}

void del(int x){
	cnt[s[x]]--;
	ans-=cnt[s[x]^k];
}


void solved(){
	read(n),read(m),read(k);
	int sz=sqrt(n);
	for(int i=1;i<=n;i++) read(s[i]),s[i]^=s[i-1],pos[i]=(i-1)/sz+1;
	for(int i=1;i<=m;i++){
		read(a[i].l),read(a[i].r);
		a[i].id=i;
	}
	sort(a+1,a+m+1,cmp);
	int l=1,r=0;cnt[0]=1ll;

	for(int i=1;i<=m;i++){
		while(l<a[i].l) {
			del(l-1);//以l为起点存在于区间[l,r] 的 sum[r]的个数
			l++;
		}
		while(l>a[i].l){
			l--;
			add(l-1);//增加以l为起点的存在于[l,r]的sum[r]的个数
		}
		while(r>a[i].r){
			del(r);//以r为终点的存在于[l,r]的sum[l]的个数 并将其删除 ans-=个数
			r--;
		}
		while(r<a[i].r){
			r++;
			add(r);//增加以r为终点的存在于l[l,r]的sum[l]的个数
		}
		val[a[i].id]=ans;
	}
	for(int i=1;i<=m;i++) writeln(val[i]);
}

int main (){
	solved();
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/81277210