• 线段树入门之单点更新


    • 作者:zifeiy
    • 标签:线段树

    单点更新 :最最基础的线段树,只更新叶子节点,然后把信息用 push_up(int rt) 这个函数更新上来

    HDU1166 敌兵布阵

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    const int maxn = 50050;
    int sum[maxn<<2];
    inline void push_up(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
    void build(int l, int r, int rt) {
        if (l == r) { cin >> sum[rt]; return; }
        int m = (l + r) >> 1;
        build(lson); build(rson); push_up(rt);
    }
    void update(int p, int add, int l, int r, int rt) {
        if (l == r) { sum[rt] += add; return; }
        int m = (l + r) >> 1;
        (p <= m) ? update(p, add, lson) : update(p, add, rson);
        push_up(rt);
    }
    int query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return sum[rt];
        int m = (l + r) >> 1, res = 0;
        if (L <= m) res += query(L, R, lson);
        if (R > m) res += query(L, R, rson);
        return res;
    }
    int T, n, a, b; char op[10];
    int main() {
        scanf("%d", &T);
        for (int cas = 1; cas <= T; cas ++) {
            printf("Case %d:
    ", cas);
            scanf("%d", &n);
            build(1, n, 1);
            while (scanf("%s", op) && op[0] != 'E') {
                scanf("%d%d", &a, &b);
                if (op[0] == 'A') update(a, b, 1, n, 1);
                else if (op[0] == 'S') update(a, -b, 1, n, 1);
                else printf("%d
    ", query(a, b, 1, n, 1));
            }
        }
        return 0;
    }
    

    HDU1754 I Hate It

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    const int maxn = 200020;
    int maxv[maxn<<2];
    inline void push_up(int rt) { maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]); }
    void build(int l, int r, int rt) {
        if (l == r) { scanf("%d", &maxv[rt]); return; }
        int m = (l + r) >> 1;
        build(lson); build(rson); push_up(rt);
    }
    void update(int p, int val, int l, int r, int rt) {
        if (l == r) { maxv[rt] = val; return; }
        int m = (l + r) >> 1;
        (p <= m) ? update(p, val, lson) : update(p, val, rson);
        push_up(rt);
    }
    int query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return maxv[rt];
        int m = (l + r) >> 1, res = 0;
        if (L <= m) res = max(res, query(L, R, lson));
        if (R > m) res = max(res, query(L, R, rson));
        return res;
    }
    int n, m, a, b; char op[10];
    int main() {
        while (~scanf("%d%d", &n, &m)) {
            build(1, n, 1);
            while (m --) {
                scanf("%s%d%d", op, &a, &b);
                if (op[0] == 'U') update(a, b, 1, n, 1);
                else printf("%d
    ", query(a, b, 1, n, 1));
            }
        }
        return 0;
    }
    

    HDU1394 Minimum Inversion Number

    • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394
    • 题目大意:给你一个长度为n的数组,你可以选择任意次数将数组的最后一个元素放到数组的最前面的那个位置(每次操作称为一次Inversion),求所有Inversion操作中数组的最小逆序对。
    • 思路:用 (O(n imes log n)) 复杂度求出最初逆序对,就可以用 (O(1)) 的复杂度分别递推求出其他解。
    • 线段树功能:
      • update:单点更新;
      • query:区间求和
    #include <bits/stdc++.h>
    using namespace std;
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    const int maxn = 5050;
    int sum[maxn<<2];
    inline void push_up(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; }
    void build(int l, int r, int rt) {
        if (l == r) { sum[rt] = 0; return; }
        int m = (l + r) >> 1;
        build(lson); build(rson); push_up(rt);
    }
    void add(int p, int l, int r, int rt) {
        if (l == r) { sum[rt] ++; return; }
        int m = (l + r) >> 1;
        (p <= m) ? add(p, lson) : add(p, rson);
        push_up(rt);
    }
    int query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return sum[rt];
        int m = (l + r) >> 1, res = 0;
        if (L <= m) res += query(L, R, lson);
        if (R > m) res += query(L, R, rson);
        return res;
    }
    int n, a[maxn], p[maxn], res, tmp;
    int main() {
        while (~scanf("%d", &n)) {
            for (int i = 0; i < n; i ++) {
                cin >> a[i];
                p[ a[i] ] = i;
            }
            build(0, n-1, 1);
            res = 0;
            for (int i = 0; i < n; i ++) {
                res += query(p[i], n-1, 0, n-1, 1);
                add(p[i], 0, n-1, 1);
            }
            tmp = res;
            for (int i = 0; i < n-1; i ++) {
                tmp += (n - 1 - a[i]) - a[i];
                res = min(res, tmp);
            }
            printf("%d
    ", res);
        }
        return 0;
    }
    

    HDU2795 Billboard

    • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
    • 题意: (h imes w) 的黑板,要贴一些一些 (1 imes L) 的海报,海报要尽可能往上放,同一高度要尽可能往左放,求每张海报放的位置。
    • 思路:每次找到最左边满足大于等于L的位置,然后减去L
    • 线段树功能:
      • query:区间求最大值的位置(直接把 update 的操作写在 query 里面了)
    #include <bits/stdc++.h>
    using namespace std;
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    const int maxn = 200020;
    int n, h, w, maxv[maxn<<2];
    inline void push_up(int rt) { maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]); }
    void build(int l, int r, int rt) {
        maxv[rt] = w;
        if (l == r) return;
        int m = (l + r) >> 1;
        build(lson); build(rson);
    }
    int query(int x, int l, int r, int rt) {
        if (l == r) { maxv[rt] -= x; return l; }
        int m = (l + r) >> 1;
        int res = (maxv[rt<<1] >= x) ? query(x, lson) : query(x, rson);
        push_up(rt);
        return res;
    }
    int main() {
        while (~scanf("%d%d%d", &h, &w, &n)) {
            if (h > n) h = n;
            build(1, h, 1);
            while (n --) {
                int x;
                scanf("%d", &x);
                if (maxv[1] < x) puts("-1");
                else printf("%d
    ", query(x, 1, h, 1));
            }
        }
        return 0;
    }
    

    练习

  • 相关阅读:
    Python-HTML基础
    异常处理
    反射hasattr; getattr; setattr; delattr
    Python 属性方法、类方法、静态方法、 特殊属性__doc__ (内建属性)
    Python3 day6面向对象
    re模块计算器作业
    re正则表达式:import re ;re.search()
    hashlib模块学习:hmac
    ConfigParser模块,主要应用于对php.ini等格式的配置文件内容读取和生成。删改较少用
    ymal文档格式 处理
  • 原文地址:https://www.cnblogs.com/codedecision/p/11676957.html
Copyright © 2020-2023  润新知