【题解】[codeforces 617E] XOR and Favorite Number【莫队】

题目链接

题意

给定序列 \(a\),非负整数 \(k\)\(m\) 次询问:\([l,r]\) 内有多少子区间的异或和为 \(k\)\(n,m\leq 10^5\)

题解

莫队。用一个桶记录当前区间内值为 \(i\) 的数的数量,移动指针时加减对应的数即可。

#include<bits/stdc++.h>
using namespace std;
int getint(){
    int ans=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9'){
        ans=ans*10+c-'0';
        c=getchar();
    }
    return ans;
}
const int N=1e5+10,M=1<<20;
#define ll long long
struct query{
    int l,r,id;
};
query q[N];
int a[N],c[M];
int n,m,k,b;

bool cmp(const query &x,const query &y){
    if(x.l/b!=y.l/b)return x.l/b<y.l/b;
    return (x.r/b<y.r/b);
}

ll ans[N];
int main(){
    n=getint(),m=getint(),k=getint();
    b=sqrt(n)+1;
    for(int i=1;i<=n;i++)a[i]=getint()^a[i-1];
    for(int i=0;i<m;i++)
        q[i].l=getint()-1,q[i].r=getint(),q[i].id=i;
    sort(q,q+m,cmp);
    int l=1,r=0;
    ll ans=0;
    for(int i=0;i<m;i++){
        while(r>q[i].r){
            c[a[r]]--;
            ans-=c[a[r]^k];
            --r;
        }
        while(r<q[i].r){
            ++r;
            ans+=c[a[r]^k];
            c[a[r]]++;
        }
        while(l<q[i].l){
            c[a[l]]--;
            ans-=c[a[l]^k];
            ++l;
        }
        while(l>q[i].l){
            --l;
            ans+=c[a[l]^k];
            c[a[l]]++;
        }
        ::ans[q[i].id]=ans;
    }
    for(int i=0;i<m;i++)printf("%lld\n",::ans[i]);
    return 0;
}
posted @ 2020-11-06 10:05  破壁人五号  阅读(73)  评论(0编辑  收藏  举报