Codeforces 617E题
链接:点击打开链接
题目简介:
输入n个数,再输入m个询问,以及k。每次询问【L,R】内有多少对l和r,满足从a[l]^.......a[r]=k。
我们想到的第一个解法就是暴力,这就不说了。。
直接附莫队算法的代码(懒得打字)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1<<20;
int n,m,k,sz;
long long L=1,R=0,Ans=0;
struct node{
int l,r,id;
}Q[maxn];
int pos[maxn];
long long flag[maxn];//记录每个前缀值的出现次数
long long ans[maxn];
int a[maxn];//记录初始状态
bool comp(node a,node b)
{
if(pos[a.l]==pos[b.l])
return a.r<b.r;
return pos[a.l]<pos[b.l];
} //首先按块进行排序,如果在同一个块内,则按区间右端点先后排序
void add(int x)
{
Ans+=flag[a[x]^k];
flag[a[x]]++;
}
void del(int x)
{
flag[a[x]]--;
Ans-=flag[a[x]^k];
}
int main()
{
scanf("%d%d%d", &n,&m,&k);
sz = sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d", &a[i]);
a[i] = a[i]^a[i-1];
pos[i] = i/sz;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id = i;
}
sort(Q+1,Q+1+m,comp);
flag[0]=1;
for(int i=1;i<=m;i++)
{
while(L<Q[i].l)
{
del(L-1);
L++;
}
while(L>Q[i].l)
{
L--;
add(L-1);
}
while(R<Q[i].r)
{
R++;
add(R);
}
while(R>Q[i].r)
{
del(R);
R--;
}
ans[Q[i].id] = Ans;//每个询问的答案
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
return 0;
}