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 }
以上是关于MZOJ #83 位运算的主要内容,如果未能解决你的问题,请参考以下文章