1. 程式人生 > >BZOJ_5301_[Cqoi2018]異或序列&&CF617E_莫隊

BZOJ_5301_[Cqoi2018]異或序列&&CF617E_莫隊

dex sans lte lin pos ati inpu xor 長度

Description

已知一個長度為 n 的整數數列 a[1],a[2],…,a[n] ,給定查詢參數 l、r ,問在 [l,r] 區間內,有多少連續子 序列滿足異或和等於 k 。 也就是說,對於所有的 x,y (l≤x≤y≤r),能夠滿足a[x]^a[x+1]^…^a[y]=k的x,y有多少組。

Input

輸入文件第一行,為3個整數n,m,k。 第二行為空格分開的n個整數,即ai,a2,….an。 接下來m行,每行兩個整數lj,rj,表示一次查詢。 1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n

Output

輸出文件共m行,對應每個查詢的計算結果。

Sample Input

4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4

Sample Output

4
2
1
2
1

分析: 把異或求前綴異或,然後莫隊,維護一個桶,加上一個$x$ 答案就加上桶裏$x\;xor\;k$的值,減去一個數同理。 代碼:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
#define N 100050
typedef long long ll;
ll ans[N],now;
int n,a[N],m,k,h[2000050],pos[N],s[N],size,block,L[N],R[N];
struct A {
    int id,l,r;
}q[N];
bool cmp(const A &x,const A &y) {
    if(pos[x.l]==pos[y.l]) return x.r<y.r;
    return pos[x.l]<pos[y.l];
}
void del(int x) {
    h[x]--;
    now-=h[x^k];
}
void add(int x) {
    now+=h[x^k];
    h[x]++;
}
void solve() {
    int l=0,r=-1,i;
    for(i=1;i<=m;i++) {
        while(l<q[i].l) del(s[l]),l++;
        while(r>q[i].r) del(s[r]),r--;
        while(l>q[i].l) l--,add(s[l]);
        while(r<q[i].r) r++,add(s[r]);
        ans[q[i].id]=now;
    }
}
int main() {
    scanf("%d%d%d",&n,&m,&k);
    int i,j;
    size=sqrt(n); block=n/size;
    pos[0]=1;
    for(i=1;i<=block;i++) {
        L[i]=R[i-1]+1; R[i]=size*i;
        for(j=L[i];j<=R[i];j++) {
            pos[j]=i;
        }
    }
    if(R[block]!=n) {
        block++; for(i=R[block-1];i<=n;i++) pos[i]=block;
    }
    for(i=1;i<=n;i++) scanf("%d",&a[i]),s[i]=s[i-1]^a[i];
    for(i=1;i<=m;i++) {
        scanf("%d%d",&q[i].l,&q[i].r); q[i].l--;
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    solve();
    for(i=1;i<=m;i++) printf("%lld\n",ans[i]);
}
/*
50 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
17 35
3 35
*/

技術分享圖片

BZOJ_5301_[Cqoi2018]異或序列&&CF617E_莫隊