树——线段树区间不一样修改操做

#1080 : 更为复杂的买卖房屋姿式

时间限制:10000msnode

单点时限:1000msios

内存限制:256MBide


描述

小Hi和小Ho都是游戏迷,“模拟都市”是他们很是喜欢的一个游戏,在这个游戏里面他们能够化身上帝模式,买卖×××。测试

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

小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但愿知道的是——每次事件发生以后,这个街道中全部房屋的房价总和是多少。spa

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

输入

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

每组测试数据的第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 6
    3195 2202 4613 3744 2892 4858 619 5079 9478 7366 8942 
    0 1 6 886
    1 0 2 9710
    1 0 10 7980
    0 4 9 -7594
    0 2 8 1581
    0 4 4 -1010
  • 样例输出

  • 58304
    75652
    87780
    42216
    53283
    52273


AC代码:在取件修改的基础上加一个add标记。

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<vector>

#include<list>

#include<iterator>

#include<string>

#include<stack>

using namespace std;

const int MAX = 1000001;


struct NODE {

int value, left, right, sum, add;

}node[MAX];


void BuildTree(int n, int left, int right) {

node[n].left = left;

node[n].right = right;

node[n].value = 0;

node[n].add = 0;

if (left == right)

{

scanf_s("%d", &node[n].sum);

return;

}

int mid = (left + right) >> 1;

BuildTree(n << 1, left, mid);

BuildTree((n << 1) | 1, mid + 1, right);

node[n].sum = node[n << 1].sum + node[(n << 1) | 1].sum;

}


void PushDown(int n) {

if (node[n].value!=0){

node[n << 1].value = node[n << 1 | 1].value = node[n].value;

node[n << 1].add = node[n << 1 | 1].add = 0;

node[n << 1].sum = (node[n << 1].right - node[n << 1].left + 1)*node[n].value;

node[n << 1 | 1].sum = (node[n << 1 | 1].right - node[n << 1 | 1].left + 1)*node[n].value;

node[n].value = 0;

}

if (node[n].add!=0)

{

node[n << 1].add += node[n].add;

node[n << 1 | 1].add += node[n].add;

node[n << 1].sum += (node[n << 1].right - node[n << 1].left + 1)*node[n].add;

node[n << 1 | 1].sum += (node[n << 1 | 1].right - node[n << 1 | 1].left + 1)*node[n].add;

node[n].add = 0;

}

}


int FindTree(int n, int begin, int end) {

int p1 = 0, p2 = 0;

if (node[n].left >= begin&&node[n].right <= end)

return node[n].sum;

PushDown(n);

if (begin <= node[n << 1].right)

p1 = FindTree(n << 1, begin, end);

if (end >= node[(n << 1) | 1].left)

p2 = FindTree((n << 1) | 1, begin, end);

node[n].sum = node[n << 1].sum + node[n << 1 | 1].sum;

return p1 + p2;

}


void UpdateTree(int n, int left, int right, int val,int flag) {

if (node[n].left >= left && node[n].right <= right)

{

if (flag == 1)

{

node[n].sum = (node[n].right - node[n].left + 1)*val;

node[n].value = val;

node[n].add = 0;

}

if (flag == 0)

{

node[n].sum += (node[n].right - node[n].left + 1)*val;

node[n].add += val;

}

return;

}

PushDown(n);

if (left <= node[n << 1].right)

UpdateTree(n << 1, left, right, val,flag);

if (right >= node[(n << 1) | 1].left)

UpdateTree((n << 1) | 1, left, right, val,flag);

node[n].sum = node[n << 1].sum + node[(n << 1) | 1].sum;


}


int main()

{

int N;

int m;

int s, l, r, v;

while (scanf_s("%d %d", &N, &m) != EOF){

BuildTree(1, 1, N+1);

for (int i = 0; i < m; i++)

{

scanf_s("%d %d %d %d", &s, &l, &r, &v);

UpdateTree(1, l+1, r+1, v, s);

printf("%d\n", FindTree(1, 1, N+1));

}

}

return 0;

}