链接:
https://www.luogu.org/problemnew/show/U47231
思路:
这道题其实就是一道双Lazy线段树裸题
因为我们知道,当k一定时,取反偶数次最后k位等于不取反
同理,当k一定时,翻转偶数次最后k位等于不取反
我们使用双Lazy分别存下这两个东西
同时一直对2取模
同时我们使用标记永久化
向下传参Lazy
单点查询到这个点时,判断是否需要取反即可
取反和翻转是位运算基本知识
大家可以看代码
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define rij register int j #define rii register int i #define rs 65536 using namespace std; struct tree{int fz,qf,val; }x[250005]; int n,k,q,t,bs[50]; void ycl() {bs[0]=1;for(rii=1;i<=25;i++){bs[i]=bs[i-1]*2;} } void cf(int val) {unsigned int kkk=val;while(kkk!=0){cout<<kkk%2<<" ";kkk/=2;}cout<<endl; } int qf(int val) {int bs=(1<<k);int ltt=val%bs;val-=ltt;ltt=-ltt;ltt--;unsigned kkk=ltt;kkk%=bs;return val+kkk; } int fz(int val) {int bis=(1<<k);int ltt=val%bis;int v=0;val-=ltt;for(rii=1;i<=k;i++){v+=(ltt%2)*bs[k-i];ltt/=2;}return val+v; } void add(int wz,int nl,int nr,int val,int bh) {if(wz==nl&&wz==nr){x[bh].val=val;return;}int mid=(nl+nr)/2;if(wz<=mid){add(wz,nl,mid,val,bh*2);}else{add(wz,mid+1,nr,val,bh*2+1);} } void change1(int l,int r,int nl,int nr,int bh) {if(l<nl){l=nl;}if(r>nr){r=nr;}if(l==nl&&r==nr){x[bh].qf++;x[bh].qf%=2;return;}int mid=(nl+nr)/2;if(l<=mid){change1(l,r,nl,mid,bh*2);}if(r>mid){change1(l,r,mid+1,nr,bh*2+1);} } void change2(int l,int r,int nl,int nr,int bh) {if(l<nl){l=nl;}if(r>nr){r=nr;}if(l==nl&&r==nr){x[bh].fz++;x[bh].fz%=2;return;}int mid=(nl+nr)/2;if(l<=mid){change2(l,r,nl,mid,bh*2);}if(r>mid){change2(l,r,mid+1,nr,bh*2+1);} } int query(int wz,int nl,int nr,int bh,int lazy1,int lazy2) {lazy1%=2;lazy2%=2;if(wz==nl&&wz==nr){lazy1+=x[bh].qf;lazy2+=x[bh].fz;int ltt=x[bh].val;if(lazy1==1){ltt=qf(ltt);}if(lazy2==1){ltt=fz(ltt);}return ltt;}int mid=(nl+nr)/2;if(wz<=mid){return query(wz,nl,mid,bh*2,lazy1+x[bh].qf,lazy2+x[bh].fz);}else{return query(wz,mid+1,nr,bh*2+1,lazy1+x[bh].qf,lazy2+x[bh].fz);} } void pd(int wz,int l,int r) {if(l==r){if(x[wz].fz!=0){x[wz].fz=0;x[wz].val=fz(x[wz].val);}if(x[wz].qf!=0){x[wz].qf=0;x[wz].val=qf(x[wz].val);}return;}if(x[wz].fz!=0){x[wz*2].fz++;x[wz*2].fz%=2;x[wz*2+1].fz++;x[wz*2+1].fz%=2;}if(x[wz].qf!=0){x[wz*2].qf++;x[wz*2].qf%=2;x[wz*2+1].qf++;x[wz*2+1].qf%=2;}x[wz].qf=0;x[wz].fz=0;int mid=(l+r)/2;pd(wz*2,l,mid);pd(wz*2+1,mid+1,r); } int main() { // freopen("XiaoX10.in","r",stdin); // freopen("XiaoX10.out","w",stdout); ycl();scanf("%d%d",&n,&t);for(rii=1;i<=n;i++){int val;scanf("%d",&val);add(i,1,rs,val,1);}for(rii=1;i<=t;i++){if(i!=1){pd(1,1,rs);}scanf("%d%d",&q,&k);int pid,l,r,wz;for(rij=1;j<=q;j++){scanf("%d",&pid);if(pid==1){scanf("%d%d",&l,&r);change1(l,r,1,rs,1);}if(pid==2){scanf("%d%d",&l,&r);change2(l,r,1,rs,1);}if(pid==3){scanf("%d",&wz);int ltt=query(wz,1,rs,1,0,0);printf("%d\n",ltt);}}}k=4; }