時間限制: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;
}