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

      

  • 相关阅读:
    Servlet的生命周期
    Servlet中的请求与响应
    Servlet中的相关的配置文件信息:
    转发与重定向的区别,笔记无法转过来,所以直接放链接了,可以直接查看
    JSP入门中的一些案例代码:
    一些已经有些模糊的小知识(一)
    JSP入门五之request,out,response对象的应用
    JSP入门四
    JSP入门三 不知道如何将笔记同步过来只能这样了
    来自(乐唯科技)的面试问题..
  • 原文地址:https://www.cnblogs.com/yplhh/p/4743234.html
Copyright © 2020-2023  润新知