【CodeForces617E】XOR and Favorite Number

来源:互联网 发布:网络推广平均工资 编辑:程序博客网 时间:2024/06/09 19:12

题目链接:

http://codeforces.com/problemset/problem/617/E

题解:

莫队算法
考虑如何进行转移,对于异或运算有一个性质,即a^a=0
那么我们就可以维护一个异或的前缀和a[i],可以O(1)查询LR的区间异或和,即a[R]^a[L1]
flag数组统计LR区间中某个值的个数,那么每次deladd时要查询a[R]^a[L1]=k的个数,根据异或运算的性质可以写成a[L1]^k=a[R],所以只需要查询flag[a[L1]^k],同时维护flag数组即可

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define LL long long#define reg register intusing namespace std;const int N=1<<20;int n,m,k,sz,L=1,R=0;LL ans[N],flag[N],Ans=0;int a[N],pos[N];struct node{    int l,r,id;}Q[N];bool cmp(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*1.0);    for(reg i=1;i<=n;i++)    {        scanf("%d",&a[i]);        a[i]=a[i]^a[i-1];        pos[i]=i/sz;    }    for(reg i=1;i<=m;i++)    {        scanf("%d%d",&Q[i].l,&Q[i].r);        Q[i].id=i;    }    flag[0]=1;    sort(Q+1,Q+m+1,cmp);    for(reg i=1;i<=m;i++)    {        while(L<Q[i].l) del(L++-1);        while(L>Q[i].l) add(--L-1);        while(R<Q[i].r) add(++R);        while(R>Q[i].r) del(R--);        ans[Q[i].id]=Ans;    }    for(int i=1;i<=m;i++)        printf("%lld\n",ans[i]);    return 0;   }
原创粉丝点击