hihocoder 1078 線段樹的區間修改 (線段樹 區間更新 模板)

_TCgogogo_發表於2016-04-01
時間限制:10000ms
單點時限:1000ms
記憶體限制:256MB

描述

對於小Ho表現出的對線段樹的理解,小Hi表示挺滿意的,但是滿意就夠了麼?於是小Hi將問題改了改,又出給了小Ho:

假設貨架上從左到右擺放了N種商品,並且依次標號為1到N,其中標號為i的商品的價格為Pi。小Hi的每次操作分為兩種可能,第一種是修改價格——小Hi給出一段區間[L, R]和一個新的價格NewP,所有標號在這段區間中的商品的價格都變成NewP。第二種操作是詢問——小Hi給出一段區間[L, R],而小Ho要做的便是計算出所有標號在這段區間中的商品的總價格,然後告訴小Hi。

那麼這樣的一個問題,小Ho該如何解決呢?

輸入

每個測試點(輸入檔案)有且僅有一組測試資料。

每組測試資料的第1行為一個整數N,意義如前文所述。

每組測試資料的第2行為N個整數,分別描述每種商品的重量,其中第i個整數表示標號為i的商品的重量Pi。

每組測試資料的第3行為一個整數Q,表示小Hi進行的運算元。

每組測試資料的第N+4~N+Q+3行,每行分別描述一次操作,每行的開頭均為一個屬於0或1的數字,分別表示該行描述一個詢問和一次商品的價格的更改兩種情況。對於第N+i+3行,如果該行描述一個詢問,則接下來為兩個整數Li, Ri,表示小Hi詢問的一個區間[Li, Ri];如果該行描述一次商品的價格的更改,則接下來為三個整數Li,Ri,NewP,表示標號在區間[Li, Ri]的商品的價格全部修改為NewP。

對於100%的資料,滿足N<=10^5,Q<=10^5, 1<=Li<=Ri<=N,1<=Pi<=N, 0<Pi, NewP<=10^4。

輸出

對於每組測試資料,對於每個小Hi的詢問,按照在輸入中出現的順序,各輸出一行,表示查詢的結果:標號在區間[Li, Ri]中的所有商品的價格之和。

樣例輸入
10
4733 6570 8363 7391 4511 1433 2281 187 5166 378 
6
1 5 10 1577
1 1 7 3649
0 8 10
0 1 4
1 6 8 157
1 3 4 1557
樣例輸出
4731
14596

題目連結:http://hihocoder.com/problemset/problem/1078

#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
int const MAX = 1e5 + 5;
int sum[MAX << 2], lazy[MAX << 2];

void PushUp(int rt)
{
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; 
}

void PushDown(int rt, int ln, int rn)
{
    if(lazy[rt])
    {
        sum[rt << 1] = ln * lazy[rt]; 
        sum[rt << 1 | 1] = rn * lazy[rt];
        lazy[rt << 1] = lazy[rt];
        lazy[rt << 1 | 1] = lazy[rt];
        lazy[rt] = 0;
    }
    return;
}

void Build(int l, int r, int rt)
{
    lazy[rt] = 0;
    if(l == r)
    {
        scanf("%d", &sum[rt]);
        return;
    }
    int mid = (l + r) >> 1;
    Build(lson);
    Build(rson);
    PushUp(rt);
    return;
}

void Update(int L, int R, int val, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        sum[rt] = (r - l + 1) * val;
        lazy[rt] = val;
        return;
    }
    int mid = (l + r) >> 1;
    PushDown(rt, mid - l + 1, r - mid);
    if(L <= mid)
        Update(L, R, val, lson);
    if(mid < R)
        Update(L, R, val, rson);
    PushUp(rt);
    return;
}

int Query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
        return sum[rt];
    int mid = (l + r) >> 1;
    PushDown(rt, mid - l + 1, r - mid);
    int ans = 0;
    if(L <= mid)
        ans += Query(L, R, lson);
    if(mid < R)
        ans += Query(L, R, rson);
    return ans;
}

int main()
{
    int n, q;
    scanf("%d", &n);
    Build(1, n, 1);
    scanf("%d", &q);
    while(q --)
    {
        int tp, l, r, val;
        scanf("%d", &tp);
        if(tp == 1)
        {
            scanf("%d %d %d", &l, &r, &val);
            Update(l, r, val, 1, n, 1);
        }
        else
        {
            scanf("%d %d", &l, &r);
            printf("%d\n", Query(l, r, 1, n, 1));
        }
    }
}


相關文章