zoukankan      html  css  js  c++  java
  • 【数据结构】线段树-区间更新最值

    仔细想想这个并不是什么正常的线段树,因为它除了PushDow有一部分信息是从上往下传递的。

    http://acm.hdu.edu.cn/showproblem.php?pid=5306

    1.区间更新min
    2.区间查询max
    3.区间查询sum

    struct SegmentTreeBeats {
    
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    #define mid ((l + r) >> 1)
    
        static const int MAXN = 2e5 + 10;
        static const int INF = 0x3f3f3f3f;
    
        int tmi[MAXN << 2];
    
        ll sum[MAXN << 2];
        int mx1[MAXN << 2], cmx[MAXN << 2], mx2[MAXN << 2];
    
        void PushUp(int u) {
            sum[u] = sum[ls] + sum[rs];
            if(mx1[ls] < mx1[rs]) {
                mx1[u] = mx1[rs], cmx[u] = cmx[rs];
                mx2[u] = max(mx1[ls], mx2[rs]);
            } else if (mx1[ls] > mx1[rs]) {
                mx1[u] = mx1[ls], cmx[u] = cmx[ls];
                mx2[u] = max(mx2[ls], mx1[rs]);
            } else {
                mx1[u] = mx1[ls], cmx[u] = cmx[ls] + cmx[rs];
                mx2[u] = max(mx2[ls], mx2[rs]);
            }
        }
    
        void PushTagMin(int u, int t) {
            if(mx1[u] <= t)
                return;
            sum[u] += 1LL * (t - mx1[u]) * cmx[u];
            mx1[u] = tmi[u] = t;
        }
    
        void PushDown(int u, int l, int r) {
            int t = tmi[u];
            if(t != INF) {
                PushTagMin(ls, t);
                PushTagMin(rs, t);
                tmi[u] = INF;
            }
        }
    
        void Build(int u, int l, int r) {
            tmi[u] = INF;
            if(l == r) {
                sum[u] = mx1[u] = a[l];
                cmx[u] = 1, mx2[u] = -INF;
                return;
            }
            Build(ls, l, mid);
            Build(rs, mid + 1, r);
            PushUp(u);
        }
    
        void UpdateMin(int u, int l, int r, int L, int R, int v) {
            if(mx1[u] <= v)
                return;
            if(L <= l && r <= R && mx2[u] < v) {
                PushTagMin(u, v);
                return;
            }
            PushDown(u, l, r);
            if(L <= mid) UpdateMin(ls, l, mid, L, R, v);
            if(R >= mid + 1) UpdateMin(rs, mid + 1, r, L, R, v);
            PushUp(u);
        }
    
        ll QuerySum(int u, int l, int r, int L, int R) {
            if (L <= l && r <= R)
                return sum[u];
            PushDown(u, l, r);
            ll res = 0;
            if(L <= mid) res += QuerySum(ls, l, mid, L, R);
            if(R >= mid + 1) res += QuerySum(rs, mid + 1, r, L, R);
            return res;
        }
    
        int QueryMax(int u, int l, int r, int L, int R) {
            if(L <= l && r <= R)
                return mx1[u];
            PushDown(u, l, r);
            int res = -INF;
            if(L <= mid) res = max(res, QueryMax(ls, l, mid, L, R));
            if(R >= mid + 1) res = max(res, QueryMax(rs, mid + 1, r, L, R));
            return res;
        }
    
    #undef ls
    #undef rs
    #undef mid
    
    } stb;
    

    用势能分析法可以得到m次操作总共是 (O(mlog n)) ?吉老师似乎说这个有问题,但是构造不出卡掉他的数据。

    混合标记:
    1.区间加法
    2.区间取min
    3.区间取max
    4.区间查询sum
    5.区间查询min
    6.区间查询max

    没有在OJ上面验证过哦,只能和另一个暴力程序对拍了。

    struct SegmentTreeBeats {
    
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    #define mid ((l + r) >> 1)
    
        static const int MAXN = 2e5 + 10;
        static const int INF = 0x3f3f3f3f;
    
        int tad[MAXN << 2], tmi[MAXN << 2], tmx[MAXN << 2];
    
        ll sum[MAXN << 2];
        int mi1[MAXN << 2], cmi[MAXN << 2], mi2[MAXN << 2];
        int mx1[MAXN << 2], cmx[MAXN << 2], mx2[MAXN << 2];
    
        void PushUp(int u) {
            sum[u] = sum[ls] + sum[rs];
            if(mi1[ls] < mi1[rs]) {
                mi1[u] = mi1[ls], cmi[u] = cmi[ls];
                mi2[u] = min(mi2[ls], mi1[rs]);
            } else if(mi1[ls] > mi1[rs]) {
                mi1[u] = mi1[rs], cmi[u] = cmi[rs];
                mi2[u] = min(mi1[ls], mi2[rs]);
            }  else {
                mi1[u] = mi1[ls], cmi[u] = cmi[ls] + cmi[rs];
                mi2[u] = min(mi2[ls], mi2[rs]);
            }
            if(mx1[ls] < mx1[rs]) {
                mx1[u] = mx1[rs], cmx[u] = cmx[rs];
                mx2[u] = max(mx1[ls], mx2[rs]);
            } else if (mx1[ls] > mx1[rs]) {
                mx1[u] = mx1[ls], cmx[u] = cmx[ls];
                mx2[u] = max(mx2[ls], mx1[rs]);
            } else {
                mx1[u] = mx1[ls], cmx[u] = cmx[ls] + cmx[rs];
                mx2[u] = max(mx2[ls], mx2[rs]);
            }
        }
    
        void PushTagAdd(int u, int l, int r, int t) {
            sum[u] += 1LL * (r - l + 1) * t;
            tad[u] += t, mi1[u] += t, mx1[u] += t;
            if(mi2[u] != INF) mi2[u] += t;
            if(tmi[u] != INF) tmi[u] += t;
            if(mx2[u] != -INF) mx2[u] += t;
            if(tmx[u] != -INF) tmx[u] += t;
        }
    
        void PushTagMin(int u, int t) {
            if(mx1[u] <= t)
                return;
            sum[u] += 1LL * (t - mx1[u]) * cmx[u];
            if(mi1[u] == mx1[u]) mi1[u] = t;
            if(mi2[u] == mx1[u]) mi2[u] = t;
            if(tmx[u] > t) tmx[u] = t;
            mx1[u] = tmi[u] = t;
        }
    
        void PushTagMax(int u, int t) {
            if(mi1[u] >= t)
                return;
            sum[u] += 1LL * (t - mi1[u]) * cmi[u];
            if(mx1[u] == mi1[u]) mx1[u] = t;
            if(mx2[u] == mi1[u]) mx2[u] = t;
            if(tmi[u] < t) tmi[u] = t;
            mi1[u] = tmx[u] = t;
        }
    
        void PushDown(int u, int l, int r) {
            int t = tad[u];
            if(t != 0) {
                PushTagAdd(ls, l, mid, t);
                PushTagAdd(rs, mid + 1, r, t);
                tad[u] = 0;
            }
            t = tmi[u];
            if(t != INF) {
                PushTagMin(ls, t);
                PushTagMin(rs, t);
                tmi[u] = INF;
            }
            t = tmx[u];
            if(t != -INF) {
                PushTagMax(ls, t);
                PushTagMax(rs, t);
                tmx[u] = -INF;
            }
        }
    
        void Build(int u, int l, int r) {
            tad[u] = 0, tmi[u] = INF, tmx[u] = -INF;
            if(l == r) {
                sum[u] = mi1[u] = mx1[u] = a[l];
                cmi[u] = 1, mi2[u] = INF;
                cmx[u] = 1, mx2[u] = -INF;
                return;
            }
            Build(ls, l, mid);
            Build(rs, mid + 1, r);
            PushUp(u);
        }
    
        void UpdateAdd(int u, int l, int r, int L, int R, int v) {
            if(L <= l && r <= R) {
                PushTagAdd(u, l, r, v);
                return;
            }
            PushDown(u, l, r);
            if(L <= mid) UpdateAdd(ls, l, mid, L, R, v);
            if(R >= mid + 1) UpdateAdd(rs, mid + 1, r, L, R, v);
            PushUp(u);
        }
    
        void UpdateMin(int u, int l, int r, int L, int R, int v) {
            if(mx1[u] <= v)
                return;
            if(L <= l && r <= R && mx2[u] < v) {
                PushTagMin(u, v);
                return;
            }
            PushDown(u, l, r);
            if(L <= mid) UpdateMin(ls, l, mid, L, R, v);
            if(R >= mid + 1) UpdateMin(rs, mid + 1, r, L, R, v);
            PushUp(u);
        }
    
        void UpdateMax(int u, int l, int r, int L, int R, int v) {
            if(mi1[u] >= v)
                return;
            if(L <= l && r <= R && mi2[u] > v) {
                PushTagMax(u, v);
                return;
            }
            PushDown(u, l, r);
            if(L <= mid) UpdateMax(ls, l, mid, L, R, v);
            if(R >= mid + 1) UpdateMax(rs, mid + 1, r, L, R, v);
            PushUp(u);
        }
    
        ll QuerySum(int u, int l, int r, int L, int R) {
            if (L <= l && r <= R)
                return sum[u];
            PushDown(u, l, r);
            ll res = 0;
            if(L <= mid) res += QuerySum(ls, l, mid, L, R);
            if(R >= mid + 1) res += QuerySum(rs, mid + 1, r, L, R);
            return res;
        }
    
        int QueryMin(int u, int l, int r, int L, int R) {
            if(L <= l && r <= R)
                return mi1[u];
            PushDown(u, l, r);
            int res = INF;
            if(L <= mid) res = min(res, QueryMin(ls, l, mid, L, R));
            if(R >= mid + 1) res = min(res, QueryMin(rs, mid + 1, r, L, R));
            return res;
        }
    
        int QueryMax(int u, int l, int r, int L, int R) {
            if(L <= l && r <= R)
                return mx1[u];
            PushDown(u, l, r);
            int res = -INF;
            if(L <= mid) res = max(res, QueryMax(ls, l, mid, L, R));
            if(R >= mid + 1) res = max(res, QueryMax(rs, mid + 1, r, L, R));
            return res;
        }
    
    #undef ls
    #undef rs
    #undef mid
    
    } stb;
    

    吉老师说 (O(mlog^2 n))

  • 相关阅读:
    【自动化测试不求人】selenium三种等待时间
    Linux中vim的简单配置
    linux中解压缩并安装.tar.gz后缀的文件
    Linux命令全称
    Linux中的find(-atime、-ctime、-mtime)指令分析
    (转)docker安装Mysql8.0并挂载外部配置和数据
    自动化测试常见Python算法题&答案
    2019年的面试经验总结-软件测试
    Python基础语法
    抓包工具Charles的使用说明
  • 原文地址:https://www.cnblogs.com/purinliang/p/14408447.html
Copyright © 2011-2022 走看看