【Codeforces587E】Duff as a Queen

来源:互联网 发布:知微数据 编辑:程序博客网 时间:2024/06/01 21:14

题意:
区间异或一个数,区间询问能异或出几个数。

线性基应该有个性质,里面有n个数,就可以异或出2n个数。
然后如果暴力O(log2n)合并两个线性基,似乎区间异或会炸。
然后你差分一下,就变成单点加了。然后再写一个树状数组支持单点查询l位置的值就好了。

#include <bits/stdc++.h>#define N 200009#define T 32#define gc getchar()#define ll long long#define mid (l+r>>1)#define root 1,1,n-1#define lc cur<<1#define rc lc|1#define lson lc,l,mid#define rson rc,mid+1,r#define now cur,l,rusing namespace std;int n,q,a[N],b[N],p[N<<2][T],number[N<<2],bit[N];int c[T<<1],d[T];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-48;    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;    return s*x;}void up(int cur,int l,int r){    int num=0;    for (int i=1;i<=number[l];i++) c[++num]=p[l][i];    for (int i=1;i<=number[r];i++) c[++num]=p[r][i];    memset(d,0,sizeof(d));    for (int i=1;i<=num;i++)    {        int Now=c[i];        for (int j=30;j>=0;j--)            if (Now>>j&1)            {                if (!d[j])                {                    d[j]=Now;                    break;                }                else Now^=d[j];            }    }    number[cur]=0;    for (int i=0;i<=30;i++)        if (d[i]) p[cur][++number[cur]]=d[i];}void build(int cur,int l,int r){    if (l==r)    {        if (b[l]==0) return;        p[cur][1]=b[l];        number[cur]=1;        return;    }    build(lson);    build(rson);    up(cur,lc,rc);}void ins(int cur,int l,int r,int x,int y){    if (l==r)    {        p[cur][1]^=y;        number[cur]=(p[cur][1]>0);        return;    }    if (x<=mid) ins(lson,x,y);    else ins(rson,x,y);    up(cur,lc,rc);}void get(int cur,int l,int r,int L,int R){    if (L>R) return;    if (L<=l&&R>=r)    {        up(0,0,cur);        return;    }    if (L<=mid) get(lson,L,R);    if (R>mid) get(rson,L,R);}int lowbit(int x){    return x&(-x);}void add(int x,int y){    for (;x<=n;x+=lowbit(x)) bit[x]^=y;}int qry(int x,int ret=0){    for (;x;x-=lowbit(x)) ret^=bit[x];    return ret;}int main(){    n=read(),q=read();    for (int i=1;i<=n;i++) a[i]=read();    for (int i=1;i<n;i++) b[i]=a[i]^a[i+1];    if (n>1) build(root);    while (q--)    {        int op=read();        if (op==1)        {            int l=read(),r=read(),k=read();            add(l,k),add(r+1,k);            if (l>1) ins(root,l-1,k);            if (r<n) ins(root,r,k);        }        else        {            int l=read(),r=read();            p[0][1]=qry(l)^a[l],number[0]=(p[0][1]>0);            if (n>1) get(root,l,r-1);            printf("%d\n",1<<number[0]);        }    }    return 0;}
原创粉丝点击