zoukankan      html  css  js  c++  java
  • 线段树

    线段树 1:单点修改,区间查询

    代码:

    /* Segment Tree 1
     * Au: GG
     */
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    
    const int N = 500005;
    
    int n, m, data[N];
    
    struct tree {
        int l, r;
        ll sum;
    } tr[N << 2]; // 四倍大小
    
    void build(int x, int y, int i) {
        tr[i].l = x, tr[i].r = y;
    
        if (x == y) tr[i].sum = data[x]; // 叶子节点直接赋值
        else {
            int mid = (x + y) >> 1;
            build(x, mid, i<<1); // 左子树
            build(mid + 1, y, i<<1|1); // 右子树
            tr[i].sum = tr[i<<1].sum + tr[i<<1|1].sum; // 回溯时维护区间和
        }
    }
    
    void update(int x, int val, int i) {
        if (tr[i].l == x && tr[i].r == x) // 找到了叶子
            tr[i].sum += val;
        else {
            int mid = (tr[i].l + tr[i].r) >> 1;
            if (x <= mid)
                update(x, val, i<<1);
            else if (x > mid)
                update(x, val, i<<1|1);
            tr[i].sum = tr[i<<1].sum + tr[i<<1|1].sum; // 回溯时维护区间和
        }
    }
    
    ll query(int x, int y, int i) {
        if (x <= tr[i].l && y >= tr[i].r) // 当前结点的区间完全被目标区间包含
            return tr[i].sum;
        else {
            int mid = (tr[i].l + tr[i].r) >> 1;
            if (x > mid) // 完全在右儿子
                return query(x, y, i<<1|1);
            else if (y <= mid) // 完全在左儿子
                return query(x, y, i<<1);
            else // 目标区间在左右都有分布
                return query(x, y, i<<1) + query(x, y, i<<1|1);
        }
    }
    
    int main() {
        scanf("%d", &n);
        scanf("%d", &m);
        for (int i = 1; i <= n; i++)
            scanf("%d", &data[i]);
        build(1, n, 1);
    
        while (m--) {
            int op, a, b;
            scanf("%d", &op);
            if (op == 1) { // 单点修改
                scanf("%d%d", &a, &b);
                update(a, b, 1);
            }
            else { // 区间求和
                scanf("%d%d", &a, &b);
                printf("%lld
    ", query(a, b, 1));
            }
        }
    
        return 0;
    }
    

    线段树 2:区间修改,区间查询

    代码:

    /* Segment Tree 2
     * Au: GG
     */
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    using namespace std;
    
    const int N = 500005;
    
    int n, m, data[N];
    
    struct tree {
        int l, r;
        ll sum, lazy;
    } tr[N << 2]; // 四倍大小
    
    void build(int x, int y, int i) {
        tr[i].l = x, tr[i].r = y;
    
        if (x == y) tr[i].sum = data[x]; // 叶子节点直接赋值
        else {
            int mid = (x + y) >> 1;
            build(x, mid, i<<1); // 左子树
            build(mid + 1, y, i<<1|1); // 右子树
            tr[i].sum = tr[i<<1].sum + tr[i<<1|1].sum; // 回溯时维护区间和
        }
    }
    
    void push_down(int i, int m) {
    	if (tr[i].lazy) {
    		tr[i<<1].lazy += tr[i].lazy;
    		tr[i<<1|1].lazy += tr[i].lazy;
    		tr[i<<1].sum += tr[i].lazy * (m - (m >> 1));
    		tr[i<<1|1].sum += tr[i].lazy * (m >> 1);
    		tr[i].lazy = 0;
    	}
    }
    
    void update(int x, int y, int val, int i) {
        if (tr[i].l >= x && tr[i].r <= y) { // 目标区间完全被覆盖
            tr[i].lazy += val;
            tr[i].sum += val * (tr[i].r - tr[i].l + 1);
            return;
        }
        else {
        	push_down(i, tr[i].r - tr[i].l + 1); // 分解下传延迟信息
            int mid = (tr[i].l + tr[i].r) >> 1;
            if (y <= mid)
                update(x, y, val, i<<1);
            else if (x > mid)
                update(x, y, val, i<<1|1);
            else
            	update(x, y, val, i<<1|1), update(x, y, val, i<<1);
            tr[i].sum = tr[i<<1].sum + tr[i<<1|1].sum; // 回溯时维护区间和
        }
    }
    
    ll query(int x, int y, int i) {
        if (x <= tr[i].l && y >= tr[i].r) // 当前结点的区间完全被目标区间包含
            return tr[i].sum;
        else {
        	push_down(i, tr[i].r - tr[i].l + 1);
            int mid = (tr[i].l + tr[i].r) >> 1;
            if (x > mid)
                return query(x, y, i<<1|1);
            else if (y <= mid)
                return query(x, y, i<<1);
            else 
                return query(x, y, i<<1) + query(x, y, i<<1|1);
        }
    }
    
    int main() {
        scanf("%d", &n);
        scanf("%d", &m);
        for (int i = 1; i <= n; i++)
            scanf("%d", &data[i]);
        build(1, n, 1);
    
        while (m--) {
            int op, a, b, c;
            scanf("%d", &op);
            if (op == 1) { // 单点修改
                scanf("%d%d%d", &a, &b, &c);
                update(a, b, c, 1);
            }
            else { // 区间求和
                scanf("%d%d", &a, &b);
                printf("%lld
    ", query(a, b, 1));
            }
        }
    
        return 0;
    }
    

    Post author 作者: Grey
    Copyright Notice 版权说明: Except where otherwise noted, all content of this blog is licensed under a CC BY-NC-SA 4.0 International license. 除非另有说明,本博客上的所有文章均受 知识共享署名 - 非商业性使用 - 相同方式共享 4.0 国际许可协议 保护。
  • 相关阅读:
    java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK
    STS工具各版本下载网址
    SpringBoot访问不了JSP但却能进入后台
    springboot o.a.tomcat.util.scan.StandardJarScanner : Failed to scan [file:/D:/apache-maven-3.0.5[系统找不到指定路径]
    STS工具:mybayis连接oracle数据库
    springBoot怎样访问静态资源?+静态资源简介
    springboot注解
    8.12-14 df 、mkswap、swapon、swapoff、sync
    8.5-7 mkfs、dumpe2fs、resize2fs
    8.2-3 partprobe、tune2fs
  • 原文地址:https://www.cnblogs.com/greyqz/p/8482433.html
Copyright © 2011-2022 走看看