BZOJ 5301: [Cqoi2018]异或序列 莫队+桶

开一个桶记录一下前缀异或值的个数即可.   

注意要把询问从 $(l,r)$ 变成 $(l-1,r)$,这样做的话会方便很多. 

code: 

#include <cstdio> 
#include <cmath>  
#include <algorithm> 
#define N 1000005    
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;       
ll ans=0ll;  
int n,m,k,B,K;     
int a[N],h[N],cnt[N];       
ll answer[N];    
struct node 
{
    int l,r,id;     
    node(int l=0,int r=0,int id=0):l(l),r(r),id(id){}  
}q[N];   
bool cmp(node x,node y)  
{
    return x.l/B==y.l/B?x.r<y.r:x.l<y.l;    
}    
void del(int x) 
{        
    ans-=cnt[K^x];  
    --cnt[x];      
}
void add(int x) 
{    
    ++cnt[x];     
    ans+=cnt[K^x];        
} 
int main() 
{ 
    // setIO("input");    
    int i,j,l=2,r=1;   
    scanf("%d%d%d",&n,&m,&K),B=sqrt(n); 
    for(i=1;i<=n;++i) scanf("%d",&a[i]),h[i]=h[i-1]^a[i];         
    for(i=1;i<=m;++i) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i,--q[i].l;    
    sort(q+1,q+1+m,cmp);     
    for(i=1;i<=m;++i) 
    {
        while(l>q[i].l) add(h[--l]);              
        while(r<q[i].r) add(h[++r]);    
        while(l<q[i].l) del(h[l++]);    
        while(r>q[i].r) del(h[r--]);     
        answer[q[i].id]=ans;  
    }   
    for(i=1;i<=m;++i) printf("%lld\n",answer[i]);   
    return 0;
}

  

posted @ 2020-02-01 16:09  EM-LGH  阅读(103)  评论(0编辑  收藏  举报