• 吉司机线段树【学习笔记】


    模板题链接

    可以从HDU-5306开始练手。

    吉司机线段树可以解决什么问题?

    譬如说区间操作:对[L, R]区间,使得L ≤ i ≤ R,a[i] = min(a[i], x)。

    然后还有区间求和、求max、min这样的操作。

    我们可以用O((n + q)log(n))的复杂度来解决这个问题。

    只需要存储这样的几个值:

    1. mx[rt]表示以rt为根的区间的最大值
    2. md[rt]表示以rt为根的区间的严格次大值
    3. cnt[rt]表示以rt为根的区间的最大值的个数
    4. sum[rt]表示以rt为根的区间和的值
    5. lazy[rt]表示以rt为根的区间,现在的懒标记(记录更新的值,但是不下推)

    然后我们可以以这五个数组来用以维护一个吉司机线段树。

    操作:

    如果mx[rt] ≤ x,那么x就是无效的更改,没用,return;

    如果md[rt] ≥ x,我们需要对于左右子树区间进行暴力更改;

    剩下的情况就是md[rt] < x < mx[rt],那么此时只需要更改目前子树的mx[rt]值就可以了,当然,我们在这里需要打lazy懒标记,因为我们不下传这个值了。

    时间复杂度的证明的关键点,就是在于对于区间的种类数的改变,因为只有暴力更改的时候才会造成高复杂度,但是会发现每次暴力更改,只会让区间的数的种类数减少,而减少的次数肯定是有限的,所以复杂度实际上不是很高。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <string>
      5 #include <cstring>
      6 #include <algorithm>
      7 #include <limits>
      8 #include <vector>
      9 #include <stack>
     10 #include <queue>
     11 #include <set>
     12 #include <map>
     13 #include <bitset>
     14 #include <unordered_map>
     15 #include <unordered_set>
     16 #define lowbit(x) ( x&(-x) )
     17 #define pi 3.141592653589793
     18 #define e 2.718281828459045
     19 #define INF 0x3f3f3f3f
     20 #define HalF (l + r)>>1
     21 #define lsn rt<<1
     22 #define rsn rt<<1|1
     23 #define Lson lsn, l, mid
     24 #define Rson rsn, mid+1, r
     25 #define QL Lson, ql, qr
     26 #define QR Rson, ql, qr
     27 #define myself rt, l, r
     28 #define pii pair<int, int>
     29 #define MP(a, b) make_pair(a, b)
     30 using namespace std;
     31 typedef unsigned long long ull;
     32 typedef unsigned int uit;
     33 typedef long long ll;
     34 const int maxN = 1e6 + 7;
     35 int N, M;
     36 int mx[maxN << 2], md[maxN << 2], cnt[maxN << 2], lazy[maxN << 2];
     37 ll sum[maxN << 2];
     38 void pushup(int rt)
     39 {
     40     sum[rt] = sum[lsn] + sum[rsn];
     41     if(mx[lsn] == mx[rsn])
     42     {
     43         mx[rt] = mx[lsn];
     44         cnt[rt] = cnt[lsn] + cnt[rsn];
     45         md[rt] = max(md[lsn], md[rsn]);
     46     }
     47     else if(mx[lsn] > mx[rsn])
     48     {
     49         mx[rt] = mx[lsn];
     50         cnt[rt] = cnt[lsn];
     51         md[rt] = max(mx[rsn], md[lsn]);
     52     }
     53     else
     54     {
     55         mx[rt] = mx[rsn];
     56         cnt[rt] = cnt[rsn];
     57         md[rt] = max(mx[lsn], md[rsn]);
     58     }
     59 }
     60 void build(int rt, int l, int r)
     61 {
     62     lazy[rt] = -1;
     63     if(l == r) { scanf("%d", &mx[rt]); md[rt] = -1; cnt[rt] = 1; sum[rt] = mx[rt]; return; }
     64     int mid = HalF;
     65     build(Lson);
     66     build(Rson);
     67     pushup(rt);
     68 }
     69 void pushdown(int rt)
     70 {
     71     if(~lazy[rt])
     72     {
     73         if(lazy[rt] < mx[lsn])
     74         {
     75             sum[lsn] = sum[lsn] - 1LL * cnt[lsn] * (mx[lsn] - lazy[rt]);
     76             mx[lsn] = lazy[rt];
     77             lazy[lsn] = lazy[rt];
     78         }
     79         if(lazy[rt] < mx[rsn])
     80         {
     81             sum[rsn] = sum[rsn] - 1LL * cnt[rsn] * (mx[rsn] - lazy[rt]);
     82             mx[rsn] = lazy[rt];
     83             lazy[rsn] = lazy[rt];
     84         }
     85         lazy[rt] = -1;
     86     }
     87 }
     88 void update(int rt, int l, int r, int ql, int qr, int val)
     89 {
     90     if(r < ql || l > qr || val >= mx[rt]) return;
     91     pushdown(rt);
     92     int mid = HalF;
     93     if(md[rt] >= val)
     94     {
     95         update(QL, val);
     96         update(QR, val);
     97         pushup(rt);
     98     }
     99     else
    100     {
    101         if(ql <= l && qr >= r)
    102         {
    103             lazy[rt] = val;
    104             sum[rt] = sum[rt] - 1LL * cnt[rt] * (mx[rt] - val);
    105             mx[rt] = val;
    106         }
    107         else
    108         {
    109             pushdown(rt);
    110             if(qr <= mid) update(QL, val);
    111             else if(ql > mid) update(QR, val);
    112             else { update(QL, val); update(QR, val); }
    113             pushup(rt);
    114         }
    115     }
    116 }
    117 int query_max(int rt, int l, int r, int ql, int qr)
    118 {
    119     if(ql <= l && qr >= r) return mx[rt];
    120     pushdown(rt);
    121     int mid = HalF;
    122     if(qr <= mid) return query_max(QL);
    123     else if(ql > mid) return query_max(QR);
    124     else return max(query_max(QL), query_max(QR));
    125 }
    126 ll query_sum(int rt, int l, int r, int ql, int qr)
    127 {
    128     if(ql <= l && qr >= r) return sum[rt];
    129     pushdown(rt);
    130     int mid = HalF;
    131     if(qr <= mid) return query_sum(QL);
    132     else if(ql > mid) return query_sum(QR);
    133     else return query_sum(QL) + query_sum(QR);
    134 }
    135 int main()
    136 {
    137     int T; scanf("%d", &T);
    138     while(T --)
    139     {
    140         scanf("%d%d", &N, &M);
    141         build(1, 1, N);
    142         for(int i=1, op, l, r, x; i<=M; i++)
    143         {
    144             scanf("%d%d%d", &op, &l, &r);
    145             switch (op)
    146             {
    147                 case 0:
    148                 {
    149                     scanf("%d", &x);
    150                     update(1, 1, N, l, r, x);
    151                     break;
    152                 }
    153                 case 1:
    154                 {
    155                     printf("%d
    ", query_max(1, 1, N, l, r));
    156                     break;
    157                 }
    158                 default:
    159                 {
    160                     printf("%lld
    ", query_sum(1, 1, N, l, r));
    161                     break;
    162                 }
    163             }
    164         }
    165     }
    166     return 0;
    167 }
    168 /*
    169 1
    170 5 2
    171 4 3 3 2 2
    172 0 2 3 2
    173 1 2 5
    174 ans:2
    175 */
  • 相关阅读:
    [SDOI2015]约数个数和
    [POI2007]ZAP-Queries
    fpu栈溢出
    shader 汇编
    sample a texture as a rendertarget
    ID3d11asynchronous
    DEVICE DRAW VERTEX BUFFER TOO SMALL
    模型的一个点显示在原点
    setrendertraget 上下颠倒
    skinned mesh 蜘蛛样
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/13705688.html
Copyright © 2020-2023  润新知