5312: 冒险
5312: 冒险
https://www.lydsy.com/JudgeOnline/problem.php?id=5312
分析:
考虑区间and,or一个数,其实是让一段区间的一些二进制位上成为0,或者1。
先考虑or:对一段区间or x,它所能更新的二进制位就是x的二进制位是1的位。在线段树上更新时,如果这段区间的x的更新的所有位都是一样的(在这个区间内这一位的要不都是0就是1),那么直接加上x可以更新的0的位就行了,就是把这些0位全设为1,1的位还是1,否则,递归处理。直到有这样的区间为止。相应的and就是让一些二进制位成为0。
每次更新的时候,其实是让x的所有更新的位变成了同一个数,所以这一段区间的这一位上全相同了,不断更新后,就会出现多个线段树区间的某一位的都一样了。复杂度为$O(nklogn)$,k为数字的位数,这里是20。
然后如何是否可以更新,记录这段区间的and和,or和,然后可以快速知道有哪些位全是1或者0,有那些位0和1都有,求出v所有更新的位上是否全相同就行了。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 200100; 20 21 int n; 22 23 #define Root 1, n, 1 24 #define lson l, mid, rt << 1 25 #define rson mid + 1, r, rt << 1 | 1 26 27 struct SegmentTree{ 28 int s1[N << 2], s8[N << 2], mx[N << 2], tag[N << 2]; 29 void pushup(int rt) { 30 s1[rt] = s1[rt << 1] | s1[rt << 1 | 1]; 31 s8[rt] = s8[rt << 1] & s8[rt << 1 | 1]; 32 mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); 33 } 34 void add(int rt,int v) { 35 s1[rt] += v, s8[rt] += v, tag[rt] += v, mx[rt] += v; 36 } 37 void pushdown(int rt) { 38 if (tag[rt]) 39 add(rt << 1, tag[rt]), add(rt << 1 | 1, tag[rt]), tag[rt] = 0; 40 } 41 bool allsame(int rt,int v,int flag) { // 判断v更新的位是不是一样的 42 if (flag == 1) 43 return ((s1[rt] | v) - s1[rt]) == ((s8[rt] | v) - s8[rt]); 44 else 45 return ((s1[rt] & v) - s1[rt]) == ((s8[rt] & v) - s8[rt]); 46 } 47 void build(int l,int r,int rt) { 48 if (l == r) { 49 s1[rt] = s8[rt] = mx[rt] = read(); 50 return ; 51 } 52 int mid = (l + r) >> 1; 53 build(lson); 54 build(rson); 55 pushup(rt); 56 } 57 void update1(int l,int r,int rt,int L,int R,int v) { 58 if ((s8[rt] | v) == s8[rt]) return ; 59 if (L <= l && r <= R && allsame(rt, v, 1)) { 60 add(rt, (s8[rt] | v) - s8[rt]); 61 return ; 62 } 63 pushdown(rt); 64 int mid = (l + r) >> 1; 65 if (L <= mid) update1(lson, L, R, v); 66 if (R > mid) update1(rson, L, R, v); 67 pushup(rt); 68 } 69 void update8(int l,int r,int rt,int L,int R,int v) { 70 if ((s1[rt] & v) == s1[rt]) return ; 71 if (L <= l && r <= R && allsame(rt, v, 8)) { 72 add(rt, (s1[rt] & v) - s1[rt]); 73 return ; 74 } 75 pushdown(rt); 76 int mid = (l + r) >> 1; 77 if (L <= mid) update8(lson, L, R, v); 78 if (R > mid) update8(rson, L, R, v); 79 pushup(rt); 80 } 81 int query(int l,int r,int rt,int L,int R) { 82 if (L <= l && r <= R) { 83 return mx[rt]; 84 } 85 int mid = (l + r) >> 1, res = 0; 86 pushdown(rt); 87 if (L <= mid) res = query(lson, L, R); 88 if (R > mid) res = max(res, query(rson, L, R)); 89 return res; 90 } 91 }T; 92 93 int main() { 94 n = read();int m = read(); 95 T.build(Root); 96 while (m --) { 97 int opt = read(), l, r, v; 98 if (opt == 1) { 99 l = read(), r = read(), v = read(); 100 T.update8(Root, l, r, v); 101 } 102 else if (opt == 2) { 103 l = read(), r = read(), v = read(); 104 T.update1(Root, l, r, v); 105 } 106 else { 107 l = read(), r = read(); 108 printf("%d\n",T.query(Root, l, r)); 109 } 110 } 111 return 0; 112 }