P4462 [CQOI2018]异或序列

P4462 [CQOI2018]异或序列

Problem:

  https://www.luogu.com.cn/problem/P4462

Solution:

  求出异或前缀和sum[],对于 a[ l ] ^ a[ l + 1] ^ .... ^ a[ r ] 就变成了sum[ r ] ^ sum[ l - 1 ],所以最终我们要求的就是在区间 [ L,R ] 中有多少子区间 [ l,r ] 是满足 sum[ r ] ^ sum[ l - 1 ] = k 的(sum[ r ] ^ sum[ l - 1 ] = k 《==》sum[ l - 1 ] = sum[ r ] ^ k 《==》sum[ r ] = k ^ sum[ l - 1 ]),变换以下就是求 [ l - 1,r ] 区间有多少个数是等于k ^ sum[ x ] (ps:x 是当前区间中新加入的数) 

  因此题目就变成了区间记数问题,而题目中可以离线处理,所以我们就可以用莫队来写。

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define _for(i,s,t) for(int i=s;i<t;i++)
#define _rof(i,s,t) for(int i=s;i>t;i--)
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define Ri(x) scanf("%d",&x)
#define Rii(x,y) scanf("%d%d",&x,&y)
#define INF 0x3f3f3f3f
using namespace std;
template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
typedef long long ll;
const int maxn = 1e5 + 10;
int a[maxn],ans[maxn],cnt[maxn],block;
struct Node{
    int l,r,i;
    friend bool operator < (Node n1,Node n2){
        if(n1.l/block != n2.l/block) return n1.l < n2.l;
        return n1.r < n2.r;
    }
}nd[maxn];
int main(){
    IOS;
    int n,m,k,v;
    cin>>n>>m>>k;
    block = sqrt(n);
    rep(i,1,n){
        cin>>v;
        a[i] = a[i - 1] ^ v;
    }
    rep(i,1,m){
        cin>>nd[i].l>>nd[i].r;
        nd[i].i = i;nd[i].l --;
    }
    sort(nd + 1,nd + 1 + m);
    int l = 1,r = 0,num = 0;
    rep(i,1,m){
        while(r < nd[i].r){
            ++r;
            num += cnt[a[r] ^ k];
            ++cnt[a[r]];
        }
        while(r > nd[i].r){
            --cnt[a[r]];
            num -= cnt[a[r] ^ k];
            --r;
        }
        while(l < nd[i].l){
            --cnt[a[l]];
            num -= cnt[a[l] ^ k];
            ++l;
        }
        while(l > nd[i].l){
            --l;
            num += cnt[a[l] ^ k];
            ++cnt[a[l]];
        }
        ans[nd[i].i] = num;
    }
    rep(i,1,n){
        cout<<ans[i]<<endl;
    }
    return 0;
}
View Code

 

posted @ 2021-01-28 12:06  Choose_and_be_chosen  阅读(172)  评论(0编辑  收藏  举报