樹——線段樹區間不同修改操作

#1080 : 更爲複雜的買賣房屋姿勢

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

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章