MZOJ #83 位运算

Posted mandy-h-y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MZOJ #83 位运算相关的知识,希望对你有一定的参考价值。

技术图片

技术图片

分析

关于位运算

位运算,不同位之间互不影响,于是有同学是一位一位来的

然鹅有大佬炸空间了

不过也有大佬过了

我倒是没有一位一位存,不过思想是一样的,

关于 & 操作

关于&操作的结果,是把原来的1变成了0,其余位不改变

也就是说,这个&操作,相当于0的or操作

关于change值

对于&的change值,如果change的这一位是1,那么这一位的答案不影响,如果这一位是0,那么区间所有数的这一位都变成了0

而 | 操作恰恰相反,

对于|的change值,如果change的这一位是0,那么这一位的答案不影响,如果这一位是1,那么区间所有数的这一位都变成了1

区间奇偶讨论

因为&操作是赋零,0的异或值一定是0所以不分奇偶讨论

因为|操作是赋一,1的异或值与奇偶有关,所以区间的异或值与区间长度的奇偶性有关

关于lazytag

某一位是0或1与区间长度的奇偶性有关,与父亲区间长无关,所以从父亲继承lazytag的时候保留原来的的值

又因为lazytag之间操作会相互影响,所以也要互相标记

关于题解

技术图片

技术图片

代码

技术图片
  1 /********************
  2 User:Mandy
  3 Language:c++
  4 Problem:
  5 ********************/
  6 //关于&操作的结果,是把原来的1变成了0,其余位不改变
  7 //也就是说,这个&操作,相当于0的or操作,
  8 //对于change,如果change的这一位是1,那么这一位的答案不影响,如果这一位是0,那么区间所有数的这一位都变成了0 
  9 //|操作恰恰相反,
 10 // 对于change,如果change的这一位是0,那么这一位的答案不影响,如果这一位是1,那么区间所有数的这一位都变成了1
 11 //接下来就是奇偶讨论了
 12 //about lazytag:与区间长度的奇偶性有关,与父亲区间长无关,所以从父亲继承的时候保留原来的的值 
 13 //&操作因为是赋零,0的异或值一定是0所以不分奇偶讨论 
 14 #include<bits/stdc++.h>
 15 #define lson l,mid,k<<1
 16 #define rson mid + 1,r,k<<1|1
 17 
 18 using namespace std;
 19 
 20 const int maxn = 2e5 + 5;
 21 
 22 int n,m,change;
 23 bool K[20]; 
 24 int tree[maxn << 2];
 25 int  lazy[maxn << 2][3];
 26 //lazy[k][0] -> & 
 27 //lazy[k][1] -> | 
 28 char *TT,*mo,but[(1 << 15) + 2];
 29 #define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 15,stdin)),TT == mo)) ? -1 : *TT++) 
 30 template<class T>inline void read(T &x){
 31     x = 0;bool flag = 0;char ch = getchar();
 32     while(!isdigit(ch)) flag |= ch == -,ch = getchar();
 33     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
 34     if(flag) x = -x;
 35 }
 36 
 37 template<class T>void putch(const T x){
 38     if(x > 9) putch(x / 10);
 39     putchar(x % 10 | 48);
 40 }
 41 
 42 template<class T>void put(const T x){
 43     if(x < 0) putchar(-),putch(-x);
 44     else putch(x);
 45 }
 46 
 47 void file(){
 48     freopen("bit8.in","r",stdin);
 49     freopen("bit.out","w",stdout);
 50 }
 51 
 52 void pushup(int k){
 53     tree[k] = tree[k<<1]^tree[k<<1|1];
 54 }
 55 
 56 void buildtree(int l,int r,int k){
 57     lazy[k][0] = (1 << 30)-1;//初值!!! 
 58     if(l == r){
 59         read(tree[k]);
 60         return;
 61     }
 62     int mid = (l + r) >> 1;
 63     buildtree(lson);
 64     buildtree(rson);
 65     pushup(k);
 66 }
 67 
 68 void readdata(){
 69     read(n);read(m);
 70     buildtree(1,n,1);
 71 }
 72 
 73 void pushdown(int l,int r,int k){
 74     int mid = (l+r)>>1;
 75     int ls = k<<1;
 76     int rs = k<<1|1;
 77     tree[ls] &= lazy[k][0];
 78     tree[rs] &= lazy[k][0];
 79     
 80     lazy[ls][0] &= lazy[k][0];
 81     lazy[rs][0] &= lazy[k][0];
 82     lazy[ls][1] &= lazy[k][0];
 83     lazy[rs][1] &= lazy[k][0];
 84     lazy[ls][1] |= lazy[k][1];
 85     lazy[ls][0] |= lazy[k][1];
 86     lazy[rs][1] |= lazy[k][1];
 87     lazy[rs][0] |= lazy[k][1];
 88     //about lazytag:与区间长度的奇偶性有关,与父亲区间长无关,所以从父亲继承的时候保留原来的的值
 89     if((mid-l+1)&1) tree[ls] |= lazy[k][1];
 90     else tree[ls] &= (((1 << 30)-1) ^ lazy[k][1]);
 91     
 92     if((r - mid) & 1) tree[rs] |= lazy[k][1];    
 93     else tree[rs] &= (((1 << 30)-1) ^ lazy[k][1]);    
 94     
 95     lazy[k][0] = (1 << 30)-1;
 96     lazy[k][1] = 0;
 97 }
 98 
 99 void And(int l,int r,int k,int x,int y){
100     if(x <= l && r <= y){
101         tree[k] &= change;
102         lazy[k][0] &= change;
103         lazy[k][1] &= change;
104         //&操作因为是赋零,0的异或值一定是0所以不分奇偶讨论 
105         //因为lazytag之间操作会相互影响,所以也要互相标记
106         return;
107     }
108     pushdown(l,r,k);
109     int mid = (l + r) >> 1;
110     if(x <= mid) And(lson,x,y);
111     if(y > mid) And(rson,x,y);
112     pushup(k);
113 }
114 
115 void Or(int l,int r,int k,int x,int y){
116     if(x <= l && r <= y){
117         if((r-l+1)&1) tree[k] |= change;
118         else tree[k] &= (((1 << 30)-1) ^change);
119         
120         lazy[k][1] |= change;
121         lazy[k][0] |= change;
122         return;
123     }
124     pushdown(l,r,k);
125     int mid = (l + r) >> 1;
126     if(x <= mid) Or(lson,x,y);
127     if(y > mid) Or(rson,x,y);
128     pushup(k);
129 }
130 
131 int  query(int l,int r,int k,int x,int y){
132     if(x <= l && r <= y) return tree[k];
133     pushdown(l,r,k);
134     int mid = (l + r) >> 1;
135     int ans = 0;
136     if(x <= mid) ans ^= query(lson,x,y);
137     if(y > mid) ans^= query(rson,x,y);    
138     return ans;
139 }
140 
141 void work(){
142     while(m--){
143         int opt,k,l,r;        
144         read(opt);
145         
146         switch(opt){//opt possible != 1 or 2 or 3
147             case 1:{
148                 read(l);read(r);
149                 read(change);
150                 And(1,n,1,l,r);
151                 break;
152             }
153             case 2:{read(l);read(r);
154                 read(change);
155                 Or(1,n,1,l,r);
156                 break;
157             }
158             case 3:{read(l);read(r);
159                 int ans = query(1,n,1,l,r);
160                 put(ans);
161                 puts("");
162                 break;
163             }
164             default:{
165                 break;
166             }
167         }
168     }
169 }
170 
171 int main(){
172 //    file();
173     readdata();
174     work();
175     return 0;
176 }
不拆位
技术图片
  1 #include<bits/stdc++.h>
  2 #define re return
  3 #define inc(i,l,r) for(register int i=l;i<=r;++i)
  4 using namespace std;
  5 template<typename T>inline void rd(T&x)
  6 {
  7     char c;bool f=0;
  8     while((c=getchar())<0||c>9)if(c==-)f=1;
  9     x=c^48;
 10     while((c=getchar())>=0&&c<=9)x=x*10+(c^48);
 11 }
 12 
 13 const int maxn=1000005;
 14 int n,m,K[20],a,ans[20];
 15 
 16 bool tr[maxn][20];
 17 int lazy[maxn][20];
 18 //tr原数,lazy懒标记 
 19 
 20 #define lson rt<<1
 21 #define rson rt<<1|1
 22 
 23 inline void pushup(int rt)
 24 {
 25     inc(i,0,19)
 26     tr[rt][i]=tr[lson][i]^tr[rson][i];
 27 }
 28 
 29 inline void build(int rt,int l,int r)
 30 {
 31     if(l==r)
 32     {
 33         rd(a);
 34         inc(i,0,19)
 35         tr[rt][i]=(a>>i)&1;
 36         re ;
 37     }
 38     
 39     int mid=(l+r)>>1;
 40     build(lson,l,mid);
 41     build(rson,mid+1,r);
 42     pushup(rt);
 43 }
 44 
 45 inline void pushdown(int rt,int l,int r,int mid)
 46 {
 47     inc(i,0,19)
 48     if(lazy[rt][i])
 49     {
 50         lazy[lson][i]=lazy[rson][i]=lazy[rt][i];
 51         if(lazy[rt][i]==1)
 52             tr[lson][i]=tr[rson][i]=0;
 53         else 
 54         {
 55             tr[lson][i]=(mid-l+1)&1;
 56             tr[rson][i]=(r-mid)&1;
 57         }
 58         lazy[rt][i]=0;
 59     }
 60 
 61 }
 62 
 63 inline void modify_and(int rt,int l,int r,int x,int y)
 64 {
 65     if(x<=l&&r<=y)
 66     {
 67         inc(i,0,19)
 68         if(!K[i])
 69         {
 70             tr[rt][i]=0;
 71             lazy[rt][i]=1;//区间赋0 
 72         }
 73         re ;
 74     }
 75     int mid=(l+r)>>1;
 76     pushdown(rt,l,r,mid);
 77     if(x<=mid)modify_and(lson,l,mid,x,y);
 78     if(y>mid)modify_and(rson,mid+1,r,x,y);
 79     
 80     pushup(rt);
 81 }
 82 
 83 inline void modify_or(int rt,int l,int r,int x,int y)
 84 {
 85     if(x<=l&&r<=y)
 86     {
 87         int f=(r-l+1)&1;
 88         inc(i,0,19)
 89         if(K[i])
 90         {
 91             tr[rt][i]=f;
 92             lazy[rt][i]=2;//区间赋1 
 93         }
 94         re ;
 95     }
 96     int mid=(l+r)>>1;
 97     pushdown(rt,l,r,mid);
 98     if(x<=mid)modify_or(lson,l,mid,x,y);
 99     if(y>mid)modify_or(rson,mid+1,r,x,y);
100     
101     pushup(rt);
102 }
103 
104 inline void ask(int rt,int l,int r,int x,int y)
105 {
106     if(x<=l&&r<=y)
107     {
108         inc(i,0,19)
109         ans[i]^=tr[rt][i];
110         re ;
111     }
112     int mid=(l+r)>>1;
113     pushdown(rt,l,r,mid);
114     if(x<=mid)ask(lson,l,mid,x,y);
115     if(y>mid) ask(rson,mid+1,r,x,y);
116 }
117 
118 int main()
119 {
120     //freopen("in.txt","r",stdin);
121     rd(n),rd(m);
122     build(1,1,n);
123     
124     int opt,k,l,r,ansnow;
125     inc(i,1,m)
126     {
127         rd(opt);
128         if(opt==3)
129         {    
130         rd(l),rd(r);
131             ansnow=0;
132             ask(1,1,n,l,r);
133             inc(j,0,17)
134             if(ans[j])
135             {
136                 ansnow|=(1<<j);
137                 ans[j]=0;
138             }
139             printf("%d
",ansnow);
140         
141         }
142         else if(opt==1||opt==2)
143         {
144             
145         rd(l),rd(r);
146             rd(k);
147             inc(j,0,17)
148             K[j]=(k>>j)&1;
149             if(opt==1)modify_and(1,1,n,l,r);    
150             else modify_or(1,1,n,l,r);
151         }
152     
153     }
154     re 0;
155 }
拆位 By LSY

 

以上是关于MZOJ #83 位运算的主要内容,如果未能解决你的问题,请参考以下文章

MZOJ #70 FFF团

向代码致敬,寻找你的第83行

MZOJ 1063 士兵守卫

MZOJ 1264 Longest

MZOJ 1132 && LuoGu P2014 选课

MZOJ 1127 && LuoGu P2016 战略游戏