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 }

 

posted @ 2018-09-13 11:19  MJT12044  阅读(293)  评论(0编辑  收藏  举报