• 初识 线段树


                  线段树

    作为一个刚接触线段树不久的OI新手,我认为线段树一般是区间或单点的查询或修改

    下面粘一些本蒟蒻的板子代码:

    洛谷:

    #include<algorithm>
    #include<cstdio>
    #define N 200001
    using namespace std;
    int n, m, a, t;
    struct nond {
        int ll, rr;
        long long sum, flag;
    }tree[4*N];
    void tree_up(int now) {
        tree[now].sum = tree[now*2].sum+tree[now*2+1].sum;
    }
    void tree_down(int now) {
        tree[now*2].flag += tree[now].flag;
        tree[now*2+1].flag += tree[now].flag;
        tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].flag;
        tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].flag;
        tree[now].flag = 0;
        return ;
    }
    void tree_build(int now, int l, int r) {
        tree[now].ll = l; tree[now].rr = r;
        if(l == r) {
            scanf("%d", &tree[now].sum);
            return ;
        }
        int mid = (l+r) / 2;
        tree_build(now*2, l, mid);
        tree_build(now*2+1, mid+1, r);
        tree_up(now);
    }
    void tree_change(int now, int l, int r) {
        if(tree[now].ll==l && tree[now].rr==r) {
            tree[now].sum += (tree[now].rr-tree[now].ll+1) * t;
            tree[now].flag += t;
            return ;
        }
        if(tree[now].flag) tree_down(now);
        int mid = (tree[now].ll+tree[now].rr) / 2;
        if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r);
        else if(r<=mid) tree_change(now*2, l, r);
                else tree_change(now*2+1, l, r);
        tree_up(now);
    }
    long long tree_query(int now, int l, int r) {
        if(tree[now].ll==l && tree[now].rr==r)
            return tree[now].sum; 
        if(tree[now].flag) tree_down(now);
        int mid = (tree[now].ll+tree[now].rr) / 2;
        if(l<=mid && mid<r) return tree_query(now*2, l, mid)+tree_query(now*2+1, mid+1, r);
        else if(r<=mid) return tree_query(now*2, l, r);
                else return tree_query(now*2+1, l, r);
    }
    int main() {
        scanf("%d%d", &n, &m);
        tree_build(1, 1, n);
        for(int i = 1; i <= m; i++) {
            scanf("%d", &a);
            if(a == 1) {
                int b, c;
                scanf("%d%d%d", &b, &c, &t);
                tree_change(1, b, c);
            }
            else {
                int b, c;
                scanf("%d%d", &b, &c);
                printf("%lld
    ", tree_query(1, b, c));
            }
        }
        return 0;
    }
    P3372【模板】线段树1
    #include<cstdio>
    #define LL long long
    #define N 100001
    using namespace std;
    int n, m, p, x, y, z, k;
    int ll[4*N], rr[4*N];
    LL flag1[4*N], flag2[4*N], sum[4*N];
    void up(int now) {
        sum[now] = (sum[now*2] + sum[now*2+1]) % p;
    }
    void down(int now) {
        if(flag1[now]!=1) {
            flag1[now*2] = flag1[now*2] * flag1[now] % p;
            flag2[now*2] = flag2[now*2] * flag1[now] % p;
            flag1[now*2+1] = flag1[now*2+1] * flag1[now] % p;
            flag2[now*2+1] = flag2[now*2+1] * flag1[now] % p;
            sum[now*2] = sum[now*2] * flag1[now] % p;
            sum[now*2+1] = sum[now*2+1] * flag1[now] % p;
            flag1[now] = 1;
        }
        if(flag2[now]) {
            flag2[now*2] = (flag2[now*2] + flag2[now]) % p;
            flag2[now*2+1] = (flag2[now*2+1] + flag2[now]) % p;
            sum[now*2] = (sum[now*2] + (rr[now*2]-ll[now*2]+1)*flag2[now]%p) % p;
            sum[now*2+1] = (sum[now*2+1] + (rr[now*2+1]-ll[now*2+1]+1)*flag2[now]%p) % p;
            flag2[now] = 0;
        }
        return ;
    }
    void build(int now, int l, int r) {
        ll[now] = l; rr[now] = r;
        flag1[now] = 1;
        if(l == r) {
            scanf("%lld", &sum[now]);
            return ;
        }
        int mid = (l+r) / 2;
        build(now*2, l, mid);
        build(now*2+1, mid+1, r);
        up(now);
    }
    void change1(int now, int l, int r) {
        if(ll[now]==l && rr[now]==r) {
            flag1[now] = flag1[now] * z %p;
            flag2[now] = flag2[now] * z % p; 
            sum[now] = sum[now] * z % p;
            return ;
        }
        if(flag2[now] || flag1[now]!=1) down(now);
        int mid = (ll[now]+rr[now]) / 2;
        if(l<=mid && mid<r) change1(now*2, l, mid), change1(now*2+1, mid+1, r);
        else if(r <= mid) change1(now*2, l, r);
                else change1(now*2+1, l, r);
        up(now);
    }
    void change2(int now, int l, int r) {
        if(ll[now]==l && rr[now]==r) {
            flag2[now] = (flag2[now] + z) % p;
            sum[now] = (sum[now] + (rr[now]-ll[now]+1)*z%p) % p;
            return ;
        }
        if(flag2[now] || flag1[now]!=1) down(now);
        int mid = (ll[now]+rr[now]) / 2;
        if(l<=mid && mid<r) change2(now*2, l, mid), change2(now*2+1, mid+1, r);
        else if(r <= mid) change2(now*2, l, r);
                else change2(now*2+1, l, r);
        up(now);
    }
    LL query(int now, int l, int r) {
        if(ll[now]==l && rr[now]==r)
            return sum[now];
        if(flag2[now] || flag1[now]!=1) down(now);
        int mid = (ll[now]+rr[now]) / 2;
        if(l<=mid && mid<r) return(query(now*2, l, mid) % p + query(now*2+1, mid+1, r) % p) % p;
        else if(r <= mid) return query(now*2, l, r) % p;
                else return query(now*2+1, l, r) % p;
    }
    int main() {
        scanf("%d%d%d", &n, &m, &p);
        build(1, 1, n);
        for(int i = 1; i <= m; i++) {
            scanf("%d", &k);
            if(k == 1) {scanf("%d%d%d", &x, &y, &z); change1(1, x, y); }
            if(k == 2) {scanf("%d%d%d", &x, &y, &z); change2(1, x, y); }
            if(k == 3) {scanf("%d%d", &x, &y); printf("%lld
    ", query(1, x, y) % p); }
        }
        return 0;
    }
    P3373【模板】线段树2

    codevs:

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #define N 100001
    using namespace std;
    int n, m;
    int a, b, c;
    struct note {
        int ll, rr;
        int sum;
    }e[4*N];
    void up(int now) {
        e[now].sum = e[now*2].sum + e[now*2+1].sum;
    }
    void build(int now, int l, int r) {
        e[now].ll = l;
        e[now].rr = r;
        if(l == r) {
            scanf("%d", &e[now].sum);
            return ;
        }
        int mid = (l+r) / 2;
        build(now*2, l, mid);
        build(now*2+1, mid+1, r);
        up(now);
    }
    void change(int now, int x, int y) {
        if(e[now].ll == e[now].rr) {
            e[now].sum += y;
            return ;
        }
        int mid = (e[now].ll+e[now].rr) / 2;
        if(x <= mid) change(now*2, x, y);
        else change(now*2+1, x, y);
        up(now);
    }
    int query(int now, int l, int r) {
        if(e[now].ll==l && e[now].rr==r) {
            return e[now].sum;
        }
        int mid = (e[now].ll+e[now].rr) / 2;
        if(l<=mid && mid<r) {
            return query(now*2, l, mid) + query(now*2+1, mid+1, r);
        }
        else if(r <= mid) return query(now*2, l, r);
                else return query(now*2+1, l, r);
    }
    int main() {
        scanf("%d", &n);
        build(1, 1, n);
        scanf("%d", &m);
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &a, &b, &c);
            if(a == 1) change(1, b, c);
            else printf("%d
    ", query(1, b, c));
        }
        return 0;
    }
    1080 线段树练习
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #define N 100001
    using namespace std;
    int n, m, flag, t;
    struct note {
        int ll, rr;
        int sum, ok;
    }tree[4*N];
    void tree_up(int now) {
        tree[now].sum = tree[now*2].sum + tree[now*2+1].sum;
    }
    void tree_down(int now) {
        tree[now*2].ok += tree[now].ok;
        tree[now*2+1].ok += tree[now].ok;
        tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].ok;
        tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].ok;
        tree[now].ok = 0;
        return ;
    }
    void tree_build(int now, int l, int r) {
        tree[now].ll = l; tree[now].rr = r;
        if(l == r) {
            scanf("%d", &tree[now].sum);
            return ;
        }
        int mid = (l+r) / 2;
        tree_build(now*2, l, mid);
        tree_build(now*2+1, mid+1, r);
        tree_up(now);
    }
    void tree_change(int now, int l, int r) {
        if(tree[now].ll==l && tree[now].rr==r) {
            tree[now].sum+=(tree[now].rr-tree[now].ll+1) * t;
            tree[now].ok += t;
            return ;
        }
        if(tree[now].ok) tree_down(now);
        int mid = (tree[now].ll+tree[now].rr) / 2;
        if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r);
        else if(r <= mid) tree_change(now*2, l, r);
                else tree_change(now*2+1, l, r);
        tree_up(now);
    }
    int tree_query(int now, int l, int r) {
        if(tree[now].ll == tree[now].rr) {
            return tree[now].sum;
        }
        if(tree[now].ok) tree_down(now);
        int mid = (l+r) / 2;
        if(t <= mid) return tree_query(now*2, l, mid);
        else return tree_query(now*2+1, mid+1, r);
    }
    int main() {
        scanf("%d", &n);
        tree_build(1, 1, n);
        scanf("%d", &m);
        for(int i = 1; i <= m; i++) {
            scanf("%d", &flag);
            if(flag == 1) {
                int a, b;
                scanf("%d%d%d", &a, &b, &t);
                tree_change(1, a, b);
            }
            else {
                scanf("%d", &t);
                printf("%d
    ", tree_query(1, 1, n));
            }
        }
        return 0;
    }
    1081 线段树练习2
    #include<algorithm>
    #include<cstdio>
    #define N 200001
    using namespace std;
    int n, m, a, t;
    struct nond {
        int ll, rr;
        long long sum, flag;
    }tree[4*N];
    void tree_up(int now) {
        tree[now].sum = tree[now*2].sum+tree[now*2+1].sum;
    }
    void tree_down(int now) {
        tree[now*2].flag += tree[now].flag;
        tree[now*2+1].flag += tree[now].flag;
        tree[now*2].sum += (tree[now*2].rr-tree[now*2].ll+1) * tree[now].flag;
        tree[now*2+1].sum += (tree[now*2+1].rr-tree[now*2+1].ll+1) * tree[now].flag;
        tree[now].flag = 0;
        return ;
    }
    void tree_build(int now, int l, int r) {
        tree[now].ll = l; tree[now].rr = r;
        if(l == r) {
            scanf("%d", &tree[now].sum);
            return ;
        }
        int mid = (l+r) / 2;
        tree_build(now*2, l, mid);
        tree_build(now*2+1, mid+1, r);
        tree_up(now);
    }
    void tree_change(int now, int l, int r) {
        if(tree[now].ll==l && tree[now].rr==r) {
            tree[now].sum += (tree[now].rr-tree[now].ll+1) * t;
            tree[now].flag += t;
            return ;
        }
        if(tree[now].flag) tree_down(now);
        int mid = (tree[now].ll+tree[now].rr) / 2;
        if(l<=mid && mid<r) tree_change(now*2, l, mid), tree_change(now*2+1, mid+1, r);
        else if(r<=mid) tree_change(now*2, l, r);
                else tree_change(now*2+1, l, r);
        tree_up(now);
    }
    long long tree_query(int now, int l, int r) {
        if(tree[now].ll==l && tree[now].rr==r)
            return tree[now].sum; 
        if(tree[now].flag) tree_down(now);
        int mid = (tree[now].ll+tree[now].rr) / 2;
        if(l<=mid && mid<r) return tree_query(now*2, l, mid)+tree_query(now*2+1, mid+1, r);
        else if(r<=mid) return tree_query(now*2, l, r);
                else return tree_query(now*2+1, l, r);
    }
    int main() {
        scanf("%d", &n);
        tree_build(1, 1, n);
        scanf("%d", &m);
        for(int i = 1; i <= m; i++) {
            scanf("%d", &a);
            if(a == 1) {
                int b, c;
                scanf("%d%d%d", &b, &c, &t);
                tree_change(1, b, c);
            }
            else {
                int b, c;
                scanf("%d%d", &b, &c);
                printf("%lld
    ", tree_query(1, b, c));
            }
        }
        return 0;
    } 
    1082 线段树练习3
  • 相关阅读:
    必须了解的经典排序算法整理
    浅谈Code Review
    NOIP2018提高组省一冲奖班模测训练(六)
    NOIP2018提高组省一冲奖班模测训练(五)
    NOIP2018提高组金牌训练营——动态规划专题
    poj 3074
    搜索中的剪枝
    bitset骚操作
    NOIP 2017 宝藏
    prim求最小生成树
  • 原文地址:https://www.cnblogs.com/v-vip/p/8506213.html
Copyright © 2020-2023  润新知