LGP5670 秘籍之反复异或 学习笔记
LGP5670 秘籍之反复异或 学习笔记
题意简述
给出一个长为 \(n\) 的序列 \(A\)。对于 \(A\) 中的所有元素我们只关心它二进制的后 \(m\) 位。需要支持两种操作:
1 l r x:区间加 \(x\)。2 l r:查询区间 \([l,r]\) 中所有元素异或和。
\(n,q\le 10^5\),\(m\le 10\)。
做法解析
这怎么做区间加?别怕,我们的 bitset 可以帮你用“暴力”过掉此题。我们对整个序列开一棵线段树,每个结点上一个 bitset 来维护当前下标区间中每种数出现的次数(刚好,反正偶数次出现一种数在最后求异或和的时候就两两消除掉了,所以我们只关心出现次数的奇偶性,正适合用 bitset)。因为 \(m\le 10\),所以 bitset 大小最大为 \(1024\),还算能接受。区间加就变成了将 bitset 上所有 b[i] 移动到 b[(i+x)%(1<<M)] 了。因为 bitset 也是可以左右移的(至于方向,注意左移是把 b[0] 往 b[1] 方向移动),所以可以直接做。查询,我们得到一个 bitset 作为结果,然后对于所有下标,若 b[i]==1 就将答案异或一个 i。
但是这样跑不过去,因为常数太大。对此我们底层分块一下即可。
代码实现
注意 t[u]=((t[u]<<x)|(t[u]>>((1<<M)-x)))&=alb;。这是必要的:这里左移之后的 t[u] 还有超出的一些位,所以要 &=alb。
#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxMa=1<<10,MaxN=1e5+5;
int N,M,Q,alf,Opt,X,Y,Z,A[MaxN],ans,B=1<<6;
bitset<MaxMa> alb;
struct SegTree{
int cl[MaxN<<2],cr[MaxN<<2];
int clen[MaxN<<2],cmid[MaxN<<2];
bitset<MaxMa> t[MaxN<<2];int tag[MaxN<<2];
int ls(int u){return u<<1;}
int rs(int u){return (u<<1)|1;}
void pushup(int u){t[u]=t[ls(u)]^t[rs(u)];}
void build(int u,int l,int r){
cl[u]=l,cr[u]=r,clen[u]=r-l+1;
if(clen[u]<=B){for(int i=l;i<=r;t[u][A[i]].flip(),i++);return;}
int mid=(l+r)>>1;cmid[u]=mid;build(ls(u),l,mid),build(rs(u),mid+1,r);pushup(u);
}
void maketag(int u,int x){
tag[u]+=x,tag[u]&=alf;
t[u]=((t[u]<<x)|(t[u]>>((1<<M)-x)))&=alb;
}
void pushdown(int u){
if(!tag[u])return;int &tt=tag[u];
maketag(ls(u),tt),maketag(rs(u),tt);tt=0;
}
void modify(int u,int dl,int dr,int x){
if(clen[u]<=B){
int bl=max(dl,cl[u]),br=min(dr,cr[u]);
for(int i=bl;i<=br;i++)t[u].flip((A[i]+tag[u])&alf),(A[i]+=x)&=alf,t[u].flip((A[i]+tag[u])&alf);
return;
}
if(dl<=cl[u]&&cr[u]<=dr){maketag(u,x);return;}
pushdown(u);
if(dl<=cmid[u])modify(ls(u),dl,dr,x);
if(dr>cmid[u])modify(rs(u),dl,dr,x);
pushup(u);
}
auto query(int u,int dl,int dr){
auto res=t[0];
if(clen[u]<=B){
int bl=max(dl,cl[u]),br=min(dr,cr[u]);
for(int i=bl;i<=br;i++)res.flip((A[i]+tag[u])&alf);
return res;
}
if(dl<=cl[u]&&cr[u]<=dr)return t[u];
pushdown(u);
if(dl<=cmid[u])res^=query(ls(u),dl,dr);
if(dr>cmid[u])res^=query(rs(u),dl,dr);
return res;
}
}SgT;
int main(){
readis(N,M,Q);alf=(1<<M)-1;
for(int i=1;i<=N;i++)readi(A[i]),A[i]&=alf;
for(int i=0;i<=alf;i++)alb[i]=1;
SgT.build(1,1,N);
for(int i=1;i<=Q;i++){
readis(Opt,X,Y);
if(Opt==1)readi(Z),SgT.modify(1,X,Y,Z);
if(Opt==2){
auto bic=SgT.query(1,X,Y);ans=0;
for(int i=0;i<=alf;i++)if(bic[i])ans^=i;
writil(ans);
}
}
return 0;
}
浙公网安备 33010602011771号