617E:XOR and Favorite Number
题意简述
给出一个
n
个元素的数列
数据范围
1≤n,q≤105
1≤ai,k≤106
1≤li≤ri≤n
思路
莫队。
先把求出前缀异或和,这样任意区间都可以通过两个前缀异或得到。
莫队的每个修改都可以在
O(1)
的时间内处理,即查询
x⊗k
出现了多少次。
总时间复杂度
O(nn√)
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int n,q,k,lim;
int seq[100010],cnt[1100010];
long long tot;
long long ans[100010];
struct ask{
int l,r,id;
bool operator < (const ask &n1) const
{
return l/lim==n1.l/lim ? r<n1.r : l/lim<n1.l/lim;
}
}a[100010];
int main()
{
scanf("%d%d%d",&n,&q,&k);
lim=int(sqrt(n));
for (int i=1;i<=n;i++)
scanf("%d",&seq[i]);
for (int i=1;i<=n;i++)
seq[i]^=seq[i-1];
for (int i=1;i<=q;i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
}
sort(a+1,a+q+1);
int l=a[1].l,r=a[1].l;
cnt[seq[l-1]]++;
tot=cnt[k^seq[a[1].l]];
cnt[seq[l]]++;
for (int i=1;i<=q;i++)
{
while (l<a[i].l)
{
cnt[seq[l-1]]--;
tot-=cnt[k^seq[l-1]];
l++;
}
while (l>a[i].l)
{
l--;
tot+=cnt[k^seq[l-1]];
cnt[seq[l-1]]++;
}
while (r<a[i].r)
{
r++;
tot+=cnt[k^seq[r]];
cnt[seq[r]]++;
}
while (r>a[i].r)
{
cnt[seq[r]]--;
tot-=cnt[k^seq[r]];
r--;
}
ans[a[i].id]=tot;
}
for (int i=1;i<=q;i++)
printf("%I64d\n",ans[i]);
return 0;
}