莫队-CF-617-E

Problem - E - Codeforces

莫队板题,唯一难点是知道如何处理区间异或

题目中说是区间,则可以转化为前缀和的形式。

令Si=a1 xor a2 xor .... xor ai;

则 al xor a(l+1) xor a(l+2) ... xor ar = Sr xor S(l-1)

然后每次询问就可转化为在 [ l-1,r ] 之间有多少个Si 和 Sj (i<=j) 使得Si xor Sj = k;

又因为Si xor Sj = k 即 Si xor k = Sj

#include<bits/stdc++.h>
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define fi first
#define se second
#define endl '\n'
#define bug printf("bug");
using namespace std;
const int N=2e5+10,S=2e6+10;
const int INF=0x3f3f3f3f;
const long long LNF=0x3f3f3f3f3f3f3f3f;
int n,m,k,len;
long long s[N],cnt[S];
long long ans=0;
long long res[S];
struct node{
	int l,r,id,from;
};
node query[S];

int get(int x){
	return x/len;
}

int cmp(const node&w,const node&q){
	if(w.from!=q.from) return w.from<q.from;
	if(w.from&1) return w.r<q.r;
	return w.r>q.r;
}

void solve(){
	scanf("%d %d %d",&n,&m,&k);
	len = max(1,(int)sqrt(n));
	for(int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]=s[i]^s[i-1];
	for(int i=1;i<=m;i++){
		int l,r; scanf("%d %d",&l,&r);
		query[i]={l,r,i,get(l)};
	}
	cnt[0]++;
	sort(query+1,query+m+1,cmp);
	int l=1,r=0;
	for(int i=1;i<=m;i++) {
		while(r<query[i].r){
			r++;
			ans+=cnt[s[r]^k];
			cnt[s[r]]++;
		}
		while(l>query[i].l){
			l--;
			ans+=cnt[s[l-1]^k];
			cnt[s[l-1]]++;
		}
		while(r>query[i].r){
			cnt[s[r]]--;
			ans-=cnt[s[r]^k];
			r--;
		}
		while(l<query[i].l){
			cnt[s[l-1]]--;
			ans-=cnt[s[l-1]^k];
			l++;
		}
		res[query[i].id] = ans;
	}
	for(int i=1;i<=m;i++){
		printf("%lld\n",res[i]);
	}
}

int main(){
	int t; t=1;
	//scanf("%d",&t);
	while(t--){
		solve();
	}
	return 0 - 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值