• 线段树维护单调栈


    例题

    淘淘摘苹果

    讲解

    • 由于单调栈在维护时,左儿子会对右儿子有影响,所以有一个 calc 函数,我的 calc 函数传入两个参数,rt 和 val,有一下三种情况
      • 如果左儿子的最大值大于 val,那么直接递归左儿子,然后加上右儿子的贡献,因为右儿子的最小值一定大于左儿子的最大值,这是在建树 pushup 时保证的。
      • 否则直接递归右儿子,因为左儿子在这时候一定是不满足的,就直接递归右儿子就行。(因为要找的是以val开始的上升序列长度)
      • 到叶子节点判断一下和 val 的大小就行。
    • pushup 的时候用左儿子和谐一下右儿子,保证单调性。

    code

    #include <bits/stdc++.h>
    using namespace std;
    inline int read() {
        int k = 0, f = 1; char ch = getchar();
        for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
        for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
        return k * f;
    }
    const int maxn = 4e5 + 100; 
    int h[maxn];
    int n, m;
    struct node { int l, r, maxx, len; } t[maxn];
    #define tl t[rt].l
    #define tr t[rt].r
    #define ls (rt << 1)
    #define rs (rt << 1 | 1)
    int calc(int rt, int val) {
        if (tl == tr) return t[rt].maxx > val;
        if (t[ls].maxx > val) return calc(ls, val) + t[rs].len;
        else return calc(rs, val);
    }
    void pushup(int rt) {
        t[rt].maxx = max(t[ls].maxx, t[rs].maxx);
        t[rs].len = calc(rs, t[ls].maxx);
    }
    void build(int rt, int l, int r) {
        tl = l, tr = r;
        if (l == r) return t[rt].maxx = h[l], void();
        int mid = (l + r) >> 1;
        build(ls, l, mid), build(rs, mid + 1, r);
        pushup(rt);
    }
    void modify(int rt, int pos) {
        if (tl == tr) return t[rt].maxx = h[pos], void();
        int mid = (tl + tr) >> 1;
        if (pos <= mid) modify(ls, pos);
        else modify(rs, pos);
        pushup(rt);
    }
    int main() {
    #ifdef debug
    #else
        freopen("taopapp.in", "r", stdin);
        freopen("taopapp.out", "w", stdout);
    #endif
        n = read(), m = read();
        for (int i = 1; i <= n; i++) h[i] = read();
        build(1, 1, n);
        while (m--) {
            int pos = read(), val = read(), tmp = h[pos];
            h[pos] = val;
            modify(1, pos);
            printf("%d
    ", calc(1, -1));
            h[pos] = tmp;
            modify(1, pos);
        }
        return 0;
    }
    
  • 相关阅读:
    【类库】容器对象(List、DataTable、 DataView、Dictionary)
    一些基础知识(一)
    编程模式之15---行为型----命令模式
    .NET学习之路----我对P/Invoke技术的理解(一)
    编程模式之十四----行为型----职责链模式
    web service 学习
    在Windows Server 2008中布置Web站点时遇到的问题及解决办法
    运算符的优先级和结合 性
    打包工具进行打包文件时要注意要点
    登录测试点
  • 原文地址:https://www.cnblogs.com/hellohhy/p/13802812.html
Copyright © 2020-2023  润新知