您的位置:首页 > 产品设计 > UI/UE

【Codeforces587E】Duff as a Queen

2017-09-27 08:03 239 查看
题意:

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

线性基应该有个性质,里面有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,r
using namespace std;
int n,q,a
,b
,p[N<<2][T],number[N<<2],bit
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: