zoukankan      html  css  js  c++  java
  • 线段树 (模板)

    功能

    (log_2n)时间复杂度对区间进行加减乘求和等等操作的数据结构。

    实现

    主要参考的是oi_wiki教程。
    记录一下板子(即HDU1166 - 敌兵布阵的代码)

    注意事项

    1. 开4倍空间,再大点更好。
    2. 叶结点不要pushdown,否则可能会越界(因为只开了4倍空间)
    //L,R均代表待处理的区间。
    //lef,rig均代表范围。
    //单点更新(覆盖),区间求和
    #include <cstdio>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    typedef long long ll;
    
    const ll maxn = 50001;
    
    ll sum[maxn << 2];
    ll lazy[maxn << 2];
    
    void pushup(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    
    void pushdown(int rt, int len) {
        if(lazy[rt]) {
            lazy[rt << 1] += lazy[rt];
            lazy[rt << 1 | 1] += lazy[rt];
            sum[rt << 1] += lazy[rt << 1] * (len - (len >> 1));
            sum[rt << 1 | 1] += lazy[rt << 1 | 1] * (len >> 1);
            lazy[rt] = 0;
        }
    }
    
    void update(int L, int R, int lef, int rig, int rt, ll val) {
        if(lef >= L && rig <= R) {
            sum[rt] += val * (rig - lef + 1);
            lazy[rt] += val;
            return ;
        }
        pushdown(rt, rig - lef + 1);
        int mid = (lef + rig) / 2;
        if(L <= mid) update(L, R, lef, mid, rt << 1, val);
        if(R > mid) update(L, R, mid + 1, rig, rt << 1 | 1, val);
        pushup(rt);
    }
    
    void build(int lef, int rig, int rt) {
        if(lef > rig) return ;
        lazy[rt] = 0;
        if(lef == rig) {
            ll tmp;
            scanf("%lld", &tmp);
            sum[rt] = tmp;
            return ;
        }
        int mid = (lef + rig) / 2;
        build(lef, mid, rt << 1);
        build(mid + 1, rig, rt << 1 | 1);
        pushup(rt);
    }
    
    ll query(int L, int R, int lef, int rig, int rt) {
        if(lef >= L && rig <= R) return sum[rt];
        pushdown(rt, rig - lef + 1);
        int mid = (lef + rig) / 2;
        ll res = 0;
        if(L <= mid) res += query(L, R, lef, mid, rt << 1);
        if(R > mid) res += query(L, R, mid + 1, rig, rt << 1 | 1);
        return res;
    }
    
    
    int main() {
        int T = 0;
        char q[10];
        scanf("%d", &T);
        for(int cases = 1; cases <= T; cases++) {
            printf("Case %d:
    ", cases);
            int n;
            scanf("%d", &n);
            build(1, n, 1);
            while(1) {
                scanf("%s", q);
                if(!strcmp(q, "Add")) {
                    int pos;
                    ll val;
                    scanf("%d%lld", &pos, &val);
                    update(pos, pos, 1, n, 1, val);
                }
                else if(!strcmp(q, "Sub")) {
                    int pos;
                    ll val;
                    scanf("%d%lld", &pos, &val);
                    update(pos, pos, 1, n, 1, -val);
                }
                else if(!strcmp(q, "Query")) {
                    int L, R;
                    scanf("%d%d", &L, &R);
                    printf("%lld
    ", query(L, R, 1, n, 1));
                }
                else if(!strcmp(q, "End")) break;
            }
        }
    }
    

    其它

    对于大范围的区间操作,可以用离散化的技巧。但是这主要处理以后线段树就不支持在线操作了。
    似乎有一种动态开点的方法可以解决这问题,有时间补上。

  • 相关阅读:
    Python单元测试之unittest基础
    linux--硬链接和软链接
    12-8 istio核心功能实战-----可观察性(程访问遥测插件)
    12-7 istio核心功能实战-----可观察性(网络可视化)
    12-6 istio核心功能实战-----可观察性(分布式追踪)
    12-3 部署面向生产的istio-----核心组件
    12 ServiceMesh代表作istio-----12-1 ServiceMes、Istio架构原理
    11-7 Grafana看板和邮件报警
    11-6 监控落地
    11-4 部署前奏-Helm&Operator
  • 原文地址:https://www.cnblogs.com/limil/p/12698239.html
Copyright © 2011-2022 走看看