hiho一下 第二十二周 (线段树上存在冲突的区间修改操作)

来源:互联网 发布:mac结束进程快捷键 编辑:程序博客网 时间:2024/06/05 21:07

题目1 : 更为复杂的买卖房屋姿势

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们可以化身上帝模式,买卖房产。

在这个游戏里,会不断的发生如下两种事件:一种是房屋自发的涨价或者降价,而另一种是政府有关部门针对房价的硬性调控。房价的变化自然影响到小Hi和小Ho的决策,所以他们希望能够知道任意时刻某个街道中所有房屋的房价总和是多少——但是很不幸的,游戏本身并不提供这样的计算。不过这难不倒小Hi和小Ho,他们将这个问题抽象了一下,成为了这样的问题:

小Hi和小Ho所关注的街道的长度为N米,从一端开始每隔1米就有一栋房屋,依次编号为0..N,在游戏的最开始,每栋房屋都有一个初始价格,其中编号为i的房屋的初始价格为p_i,之后共计发生了M次事件,所有的事件都是对于编号连续的一些房屋发生的,其中第i次事件如果是房屋自发的涨价或者降价,则被描述为三元组(L_i, R_i, D_i),表示编号在[L_i, R_i]范围内的房屋的价格的增量(即正数为涨价,负数为降价)为D_i;如果是政府有关部门针对房价的硬性调控,则被描述为三元组(L_i, R_i, V_i),表示编号在[L_i, R_i]范围内的房屋的价格全部变为V_i。而小Hi和小Ho希望知道的是——每次事件发生之后,这个街道中所有房屋的房价总和是多少。

提示:这是练习向的一周~

输入

每个测试点(输入文件)有且仅有一组测试数据。

每组测试数据的第1行为两个整数N、M,分别表示街道的长度和总共发生的事件数。

每组测试数据的第2行为N+1个整数,其中第i个整数位p_i,表示编号为i的房屋的初始价格。

每组测试数据的第3-M+2行,按照发生的时间顺序,每行描述一个事件,如果该行描述的事件为,“房屋自发的涨价或者降价”,则该行为4个整数0, L_i, R_i, D_i,意义如前文所述;如果该行描述的事件为“政府有关部门针对房价的硬性调控”,则该行为4个整数1, L_i, R_i, V_i,意义如前文所述。

对于100%的数据,满足N<=10^5,1<=p_i, |D_i|, V_i<=10^4,0<=l_i<r_i<=n。<>

对于100%的数据,满足在任意时刻,任何房屋的价格都处于[1, 10^4]内。

输出

对于每组测试数据,输出M行,其中第i行为一个整数Ans_i,表示第i次事件发生之后,这个街道中所有房屋的房价总和。


样例输入
10 63195 2202 4613 3744 2892 4858 619 5079 9478 7366 8942 0 1 6 8861 0 2 97101 0 10 79800 4 9 -75940 2 8 15810 4 4 -1010
样例输出
5830475652877804221653283

52273


说明:题目中有两种修改操作——并且都是区间修改,也就是说如果使用懒惰标记来维护修改的话,关键在于处理好这两种操作之间的冲突。

代码:

#include <iostream>#include <cstdio>using namespace std;const int MAXN = 100005;int N, M;int segTree[MAXN*3];int lazySet[MAXN*3];int lazyAdd[MAXN*3];void pushUp(int node){    segTree[node] = segTree[2*node] + segTree[2*node+1];}void pushDown(int node, int begin, int end){    int m = (begin+end)/2;    if(lazySet[node]){        lazyAdd[2*node] = lazyAdd[2*node+1] = 0; //最关键的在此        lazySet[2*node] = lazySet[2*node+1] = lazySet[node];        segTree[2*node] = (m-begin+1)*lazySet[node];        segTree[2*node+1] = (end-m)*lazySet[node];        lazySet[node] = 0;    }    if(lazyAdd[node]){        lazyAdd[2*node] += lazyAdd[node];        lazyAdd[2*node+1] += lazyAdd[node];        segTree[2*node] += (m-begin+1)*lazyAdd[node];        segTree[2*node+1] += (end-m)*lazyAdd[node];        lazyAdd[node] = 0;    }}void build(int node, int begin, int end){    lazySet[node] = lazyAdd[node] = 0;    if(begin == end) scanf("%d", &segTree[node]);    else{        int m = (begin+end)/2;        build(2*node, begin, m);        build(2*node+1, m+1, end);        pushUp(node);    }}void updateAdd(int node, int begin, int end, int a, int b, int c){    if(begin==a && end==b){        lazyAdd[node] += c;        segTree[node] += (b-a+1)*c;    }else{        pushDown(node, begin, end);        int m = (begin+end)/2;        if(b<=m) updateAdd(2*node, begin, m, a, b, c);        else if(m<a) updateAdd(2*node+1, m+1, end, a, b, c);        else{            updateAdd(2*node, begin, m, a, m, c);            updateAdd(2*node+1, m+1, end, m+1, b, c);        }        pushUp(node);    }}void updateSet(int node, int begin, int end, int a, int b, int c){    if(begin==a && end==b){        lazySet[node] = c;        lazyAdd[node] = 0;        segTree[node] = (b-a+1)*c;    }else{        pushDown(node, begin, end);        int m = (begin+end)/2;        if(b<=m) updateSet(2*node, begin, m, a, b, c);        else if(a>m) updateSet(2*node+1, m+1, end, a, b, c);        else{            updateSet(2*node, begin, m, a, m, c);            updateSet(2*node+1, m+1, end, m+1, b, c);        }        pushUp(node);    }}int main(){    int type, a, b, c;    scanf("%d %d", &N, &M);    build(1, 1, N+1);    while(M--){        scanf("%d %d %d %d", &type, &a, &b, &c);        a++; b++;        if(type == 0){            //房屋自发的涨价或者降价            updateAdd(1, 1, N+1, a, b, c);        }else{            //政府有关部门针对房价的硬性调控            updateSet(1, 1, N+1, a, b, c);        }        printf("%d\n", segTree[1]);    }    return 0;}


代码二(更简洁和高效一点,其实二者效率差不太多)

#include <iostream>#include <cstdio>using namespace std;const int MAXN = 100005;int N, M;int segTree[MAXN*3];int lazySet[MAXN*3];int lazyAdd[MAXN*3];void pushUp(int node){    segTree[node] = segTree[node<<1] + segTree[node<<1|1];}void pushDown(int node, int begin, int end){    int m = (begin+end)>>1;    if(lazySet[node]){        lazyAdd[node<<1] = lazyAdd[node<<1|1] = 0;        lazySet[node<<1] = lazySet[node<<1|1] = lazySet[node];        segTree[node<<1] = (m-begin+1)*lazySet[node];        segTree[node<<1|1] = (end-m)*lazySet[node];        lazySet[node] = 0;    }    if(lazyAdd[node]){        lazyAdd[node<<1] += lazyAdd[node];        lazyAdd[node<<1|1] += lazyAdd[node];        segTree[node<<1] += (m-begin+1)*lazyAdd[node];        segTree[node<<1|1] += (end-m)*lazyAdd[node];        lazyAdd[node] = 0;    }}void build(int node, int begin, int end){    lazySet[node] = lazyAdd[node] = 0;    if(begin == end){        scanf("%d", &segTree[node]);        return;    }    int m = (begin+end)>>1;    build(node<<1, begin, m);    build(node<<1|1, m+1, end);    pushUp(node);}void updateAdd(int node, int begin, int end, int a, int b, int c){    if(a<=begin && end<=b){        lazyAdd[node] += c;        segTree[node] += (end-begin+1)*c;        return;    }    pushDown(node, begin, end);    int m = (end+begin)>>1;    if(a<=m) updateAdd(node<<1, begin, m, a, b, c);    if(m<b) updateAdd(node<<1|1, m+1, end, a, b, c);    pushUp(node);}void updateSet(int node, int begin, int end, int a, int b, int c){    if(a<=begin && end<=b){        lazySet[node] = c;        lazyAdd[node] = 0;        segTree[node] = (end-begin+1)*c;        return;    }    pushDown(node, begin, end);    int m = (begin+end)>>1;    if(a<=m) updateSet(node<<1, begin, m, a, b, c);    if(m<b) updateSet(node<<1|1, m+1, end, a, b, c);    pushUp(node);}int main(){    int type, a, b, c;    scanf("%d %d", &N, &M);    build(1, 1, N+1);    while(M--){        scanf("%d %d %d %d", &type, &a, &b, &c);        a++; b++;        if(type == 0){            //房屋自发的涨价或者降价            updateAdd(1, 1, N+1, a, b, c);        }else{            //政府有关部门针对房价的硬性调控            updateSet(1, 1, N+1, a, b, c);        }        printf("%d\n", segTree[1]);    }    return 0;}


0 0