【BZOJ5301】【CQOI2018】异或序列(莫队)

【BZOJ5301】【CQOI2018】异或序列(莫队)

题面

BZOJ
洛谷

Description

已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。

Input

输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n

Output

输出文件共m行,对应每个查询的计算结果。

Sample Input

4 5 1

1 2 3 1

1 4

1 3

2 3

2 4

4 4

Sample Output

4

2

1

2

1

题解

板子题+原题
我也没有什么好说的了。
果然是模板大赛啊。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
ll ans[MAX],Ans;
int n,m,K,blk,num[MAX],a[MAX];
struct Query{int l,r,id,lb;}q[MAX];
bool operator<(Query a,Query b){if(a.lb!=b.lb)return a.lb<b.lb;return a.r<b.r;}
void Add(int x){Ans+=num[K^a[x]],++num[a[x]];}
void Del(int x){--num[a[x]],Ans-=num[K^a[x]];}
int main()
{
	n=read();m=read();K=read();blk=sqrt(n);
	for(int i=1;i<=n;++i)a[i]=read()^a[i-1];
	for(int i=1;i<=m;++i)
	{
		int l=read(),r=read();
		q[i]=(Query){l-1,r,i,l/blk};
	}
	sort(&q[1],&q[m+1]);
	int L=0,R=-1;
	for(int i=1;i<=m;++i)
	{
		while(R<q[i].r)Add(++R);
		while(L>q[i].l)Add(--L);
		while(L<q[i].l)Del(L++);
		while(R>q[i].r)Del(R--);
		ans[q[i].id]=Ans;
	}
	for(int i=1;i<=m;++i)printf("%lld
",ans[i]);
	return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/8901055.html