zoukankan      html  css  js  c++  java
  • 线段树II--区间修改

      题意:假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi。小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP。第二种操作是询问——小Hi给出一段区间[L, R],而小Ho要做的便是计算出所有标号在这段区间中的商品的总价格,然后告诉小Hi。

      需要用到推迟对子节点的更新。直接更新孩子节点没有必要,这样会增加时间复制的。当访问到的时候再去更新孩子节点。

      还是使用数组来存储完全二叉树的结构,初始化时,lazy都为false。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    #define M 100005
    int arr[M];
    struct Node{
        int l, r, sum;
        bool lazy;
    };
    Node nodes[4 * M];
    
    void buildTree(int l, int r, int i){
        nodes[i].l = l;
        nodes[i].r = r;
        nodes[i].lazy = false;
        if (l == r){
            nodes[i].sum = arr[l];
            return;
        }
        int mid = (l + r) >> 1;
        buildTree(l, mid, i * 2);
        buildTree(mid + 1, r, i * 2 + 1);
        nodes[i].sum = nodes[i * 2].sum + nodes[i * 2 + 1].sum; //!!!
    }
    
    void update(int l, int r, int v, int i){
        if (nodes[i].lazy)
            pushdown(i);
        if (nodes[i].l == l && nodes[i].r == r){
            nodes[i].sum = (nodes[i].r - nodes[i].l + 1)*v;
            nodes[i].lazy = true;
            return;
        }
        int mid = (nodes[i].l + nodes[i].r) >> 1;
        if (r <= mid)
            update(l, r, v, i * 2);
        else if (l > mid)
            update(l, r, v, i * 2 + 1);
        else{
            update(l, mid, v, i * 2);
            update(mid + 1, r, v, i * 2 + 1);
        }
        nodes[i].sum = nodes[i * 2].sum + nodes[i * 2 + 1].sum; //!!!
    }
    
    void pushdown(int i){
        if (nodes[i].lazy){
            nodes[i * 2].lazy = true;
            nodes[i * 2 + 1].lazy = true;
            nodes[i].lazy = false;
            int avg = nodes[i].sum / (nodes[i].r - nodes[i].l + 1);
            nodes[i * 2].sum = avg * (nodes[i * 2].r - nodes[i].l + 1);
            nodes[i * 2 + 1].sum = avg * (nodes[i * 2 + 1].r - nodes[i * 2 + 1].l + 1);
        }
    }
    
    int query(int l, int r, int i){
        if (nodes[i].lazy)
            pushdown(i);
        if (nodes[i].l == l && nodes[i].r == r){
            return nodes[i].sum;
        }
        int mid = (nodes[i].l + nodes[i].r) >> 1;
        if (r <= mid){
            return query(l, r, i * 2);
        }
        else if (l > mid){
            return query(l, r, i * 2 + 1);
        }
        else{
            return query(l, mid, 2 * i) + query(mid + 1, r, 2 * i + 1);
        }
    }
    
    int main(){
        int i, m, n, f, l, r, price;
        while (scanf("%d", &n) != EOF){
            for (i = 1; i <= n; ++i){
                scanf("%d", &arr[i]);
            }
            buildTree(1, n, 1);
            scanf("%d", &m);
            while (m--){
                scanf("%d", &f);
                if (f == 1){
                    scanf("%d%d%d", &l, &r, &price);
                    update(l, r, price, 1);
                }
                else{
                    scanf("%d%d", &l, &r);
                    printf("%d
    ", query(l, r, 1));
                }
            }
        }
        return 0;
    }

      

  • 相关阅读:
    OSI安全体系结构
    PHP 二维数组根据相同的值进行合并
    Java实现 LeetCode 17 电话号码的字母组合
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 16 最接近的三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 15 三数之和
    Java实现 LeetCode 14 最长公共前缀
  • 原文地址:https://www.cnblogs.com/yplhh/p/4743234.html
Copyright © 2011-2022 走看看