线段树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;
}

  

原文地址:https://www.cnblogs.com/yplhh/p/4743234.html