zoukankan      html  css  js  c++  java
  • 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
    ",T.query(Root, l, r));
    109         }
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    2019中山纪念中学夏令营-Day19 数论初步【GCD(最大公约数),素数相关】
    2019中山纪念中学夏令营-Day14 图论初步【dijkstra算法求最短路】
    2019中山纪念中学夏令营-Day12[JZOJ]
    2019中山纪念中学夏令营-Day9[JZOJ](第六次模拟赛)
    2019中山纪念中学夏令营-Day4[JZOJ]
    2019中山纪念中学夏令营-Day2[JZOJ]
    2019中山纪念中学夏令营-Day1[JZOJ]
    CCPC2019江西省赛-Problem G.Traffic
    T137223 节能主义
    T137226 彩虹海
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9639433.html
Copyright © 2011-2022 走看看