LuoguP4462 [CQOI2018]异或序列

LuoguP4462 [CQOI2018]异或序列

题面

链接

 

题解

异或的逆运算就是其本身

即a xor b = c 即 c xor a = b

对于本题,

记录一下1-i的异或和为sum[i]

显然L~R的异或和就为sum[L-1] xor sum[R]

若为异或和为K即满足sum[R] xor K = sum[L-1]

开个桶,莫队即可

注意一下莫队处理时删除一个数时的顺序就好了

#include<bits/stdc++.h>

using namespace std;

#define LL long long

inline LL read()
{
    LL f = 1,x = 0;
    char ch;
    do
    {
        ch = getchar();
        if(ch == -) f=-1;
    }while(ch<0||ch>9);
    do
    {
        x = (x<<3) + (x<<1) + ch - 0;
        ch = getchar();
    }while(ch>=0&&ch<=9);
    return f*x;
}

const int MAXN = 100000 + 10;

struct Query
{
    int l;
    int r;
    int id;
}q[MAXN];



int n,m,k,sz;
int a[MAXN],sum[MAXN];
int bol[MAXN];
int ans[MAXN];
int cnt[MAXN];

inline bool cmp(Query a1,Query a2)
{
    return (bol[a1.l]^bol[a2.l])?bol[a1.l]<bol[a2.l]:(bol[a1.l]&1)?a1.r<a2.r:a1.r>a2.r;
}

int main()
{
    n = read();m=read();k=read();
    sz = sqrt(2*n/3);
    for(int i=1;i<=n;i++) a[i]=read(),bol[i]=(i-1)/sz+1;
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]^a[i];
    for(int i=1;i<=m;i++)
    {
        q[i].id = i;
        q[i].l = read() - 1;
        q[i].r = read();
    }
    sort(q+1,q+m+1,cmp);
    int l = 1,r = 0;         
    int res = 0;
    for(int i=1;i<=m;i++)
    {

        while(r<q[i].r) r++,res+=cnt[sum[r]^k],cnt[sum[r]]++;
        while(r>q[i].r) cnt[sum[r]]--,res-=cnt[sum[r]^k],r--;
        while(l<q[i].l) cnt[sum[l]]--,res-=cnt[sum[l]^k],l++;
        while(l>q[i].l) l--,res+=cnt[sum[l]^k],cnt[sum[l]]++;
        ans[q[i].id] = res;
    }
    for(int i=1;i<=m;i++) 
    {
        cout<<ans[i]<<endl;
    }
}
相关文章
相关标签/搜索
每日一句
    每一个你不满意的现在,都有一个你没有努力的曾经。
公众号推荐
   一个历史类的公众号,欢迎关注
一两拨千金