• BZOJ 5312: 冒险


    首先我们考虑,对于And 和 Or 操作,对于操作位上只有And 0 和 Or 1 是有效果的。

    我们注意到如果区间内需要改动的操作位上的数字都相同,那么是可以区间取与以及区间取或的。

    那其实可以维护出这个区间的$区间与x和区间或y$

    我们考虑 $某一位上 x;  xor ; y == 1 时$

    必定是$x 那一位上 是0 ; y 那一位上是1$

    因为显然 $如果x那一位上是1,那么y那一位上必然是1, y那一位上是0, x 那一位上必然是0$

    那我们再考虑区间与的操作,我们令 $S = (1 << 31) - 1, 令val 表示需要与的数$

    当 $(x ; xor ; y) ; and ; (S - val) == 0 的时候$

    这个时候可以理解为在不需要与0的位置上,这个区间内都是1或者都是0,即这些不相关位对我们的区间取与操作不会有影响。

    再考虑如何标记$lazy, 对And 和 Or 分别设置一个lazyA 和 lazyO $

    $我们注意到,要取与的时候,把lazyA 一并与上, 并且把lazyO也要与上$

    取或的时候只给$lazyO$取或就可以。

    区间取或的操作分析同理。

    再简陋的证明一下复杂度:

    假设我们考虑要处理的一段区间不能进行区间处理,需要一位一位处理,但是我们这次处理之后这一段区间就可以区间处理了

    再考虑,对于一段已经完好的区间,我们对它区间处理,它就会分成三段,但实际上这次的处理是$log的$

    再考虑下一次处理,实际上两头又是好的,感觉又是$log$..

    好吧 不口胡了,还是放官方的复杂度证明吧。。

    https://csacademy.com/contest/round-70/task/and-or-max/solution

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 200010
      5 int n, q, arr[N], S = (1 << 31) - 1; 
      6 
      7 struct SEG
      8 {
      9     struct node
     10     {
     11         int Max, A, O, lazyA, lazyO;
     12         node() {}
     13         node(int x)
     14         {
     15             Max = A = O = x;
     16             lazyA = S;
     17             lazyO = 0;
     18         }
     19         node operator + (const node &r) const
     20         {
     21             node res = node(0);
     22             res.Max = max(Max, r.Max);
     23             res.A = A & r.A;
     24             res.O = O | r.O;
     25             return res;
     26         }
     27         void add(int And, int Or)
     28         {
     29             Max = Max & And | Or;
     30             A = A & And | Or;
     31             O = O & And | Or;
     32             lazyA = lazyA & And;
     33             lazyO = lazyO & And | Or;
     34         }
     35     }a[N << 2];
     36     void build(int id, int l, int r)
     37     {
     38         if (l == r)
     39         {
     40             a[id] = node(arr[l]);
     41             return;
     42         }
     43         int mid = (l + r) >> 1;
     44         build(id << 1, l, mid);
     45         build(id << 1 | 1, mid + 1, r);
     46         a[id] = a[id << 1] + a[id << 1 | 1];
     47     }
     48     void pushdown(int id)
     49     {
     50         if (a[id].lazyA != S || a[id].lazyO)
     51         {
     52             a[id << 1].add(a[id].lazyA, a[id].lazyO);
     53             a[id << 1 | 1].add(a[id].lazyA, a[id].lazyO);
     54             a[id].lazyA = S;
     55             a[id].lazyO = 0;
     56         }
     57     }
     58     void updateA(int id, int l, int r, int ql, int qr, int val)
     59     {
     60         if (l >= ql && r <= qr && !((a[id].A ^ a[id].O) & (S ^ val)))
     61         {
     62             a[id].add(val, 0);
     63             return;
     64         }
     65         pushdown(id);
     66         int mid = (l + r) >> 1;
     67         if (ql <= mid) updateA(id << 1, l, mid, ql, qr, val);
     68         if (qr > mid) updateA(id << 1 | 1, mid + 1, r, ql, qr, val);
     69         a[id] = a[id << 1] + a[id << 1 | 1];
     70     }
     71     void updateO(int id, int l, int r, int ql, int qr, int val)
     72     {
     73         if (l >= ql && r <= qr && !((a[id].A ^ a[id].O) & val)) 
     74         {
     75             a[id].add(S, val);
     76             return;
     77         }
     78         pushdown(id);
     79         int mid = (l + r) >> 1;
     80         if (ql <= mid) updateO(id << 1, l, mid, ql, qr, val);
     81         if (qr > mid) updateO(id << 1 | 1, mid + 1, r, ql, qr, val);
     82         a[id] = a[id << 1] + a[id << 1 | 1];
     83     }
     84     int query(int id, int l, int r, int ql, int qr)
     85     {
     86         if (l >= ql && r <= qr) return a[id].Max;
     87         pushdown(id);
     88         int mid = (l + r) >> 1;
     89         int res = 0;
     90         if (ql <= mid) res = max(res, query(id << 1, l, mid, ql, qr));
     91         if (qr > mid) res = max(res, query(id << 1 | 1, mid + 1, r, ql, qr));
     92         a[id] = a[id << 1] + a[id << 1 | 1];
     93         return res;
     94     }
     95 }seg;
     96 
     97 
     98 void Run()
     99 {
    100     while (scanf("%d%d", &n, &q) != EOF)
    101     {
    102         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
    103         seg.build(1, 1, n);
    104         for (int qq = 1, op, l, r, x; qq <= q; ++qq)
    105         {
    106             scanf("%d%d%d", &op, &l, &r);
    107             if (op == 3) printf("%d
    ", seg.query(1, 1, n, l, r));
    108             else
    109             {
    110                 scanf("%d", &x);
    111                 if (op == 1) seg.updateA(1, 1, n, l, r, x);
    112                 else seg.updateO(1, 1, n, l, r, x);
    113             }
    114         }
    115     }
    116 }
    117 
    118 int main()
    119 {
    120     #ifdef LOCAL
    121         freopen("Test.in", "r", stdin);
    122     #endif 
    123 
    124     Run();
    125     return 0;
    126 }
    View Code
  • 相关阅读:
    javascript 正則表達式补充
    NOIP2010 引水入城
    [Elasticsearch] 集群的工作原理
    师傅快看!全国首个民间资本为主的物联网行业投融资平台诞生了!
    【解决】hive与hbase表结合级联查询的问题
    ssh2项目整合 struts2.1+hibernate3.3+spring3 基于hibernate注解和struts2注解
    Python网络爬虫(一):初步认识网络爬虫
    Android天气预报+百度天气接口
    《从零開始学Swift》学习笔记(Day 55)——使用try?和try!差别
    使用SQL Profile及SQL Tuning Advisor固定运行计划
  • 原文地址:https://www.cnblogs.com/Dup4/p/9970887.html
Copyright © 2020-2023  润新知