POJ 3468 A Simple Problem with Integers 線段樹維護動態區間和

 題目鏈接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66989#problem/C

題意:給定一個數組,然後動態修改某些區間的值,並詢問某些區間的和。

思路:既然是線段樹專題,那就用線段樹了。這是一個標準的線段樹維護動態區間和問題,很顯然,我們需要維護的是這些連續區間的和,當我們對某個子區間進行add操作時,必然會對這個子區間的上一個區間的和值產生影響,也就是說,対小區間的操作會對大區間的和值產生影響。所以當我們修改一個區間[a,b]的值時,還得修改他的上面的間的和值,但是,[a,b]和他下面的區間的和值就不用在去訪問了,我們可以再維護一個add值,表示每個區間的修改的值,這樣,在query時,在累加他上面的區間的add就行了(大區間的add包含對子區間add)。這樣一來,需要維護的變量就是add操作和sum值了。


代碼:

#include<iostream>
#include<cstdio>
#define LL long long
#define maxn 100010

using namespace std;
struct node{
    int l,r;
    LL s,w;//記錄該區間的和值,add操作
}T[maxn*3];

int N,Q,A[maxn];

LL build(int L,int R,int o){//初始化線段樹
    T[o].l=L;T[o].r=R;T[o].w=0;
    if(L==R) return T[o].s=A[L];
    return T[o].s=build(L,(L+R)/2,o*2)+build((L+R)/2+1,R,o*2+1);
}

void add(int L,int R,int val,int o){
    if(T[o].l==L && T[o].r==R){//注意這裏用的是==號
        T[o].w+=val;return;//記錄該區間的add操作,但是可以不用更新該區間的和值
    }
    T[o].s+=(R-L+1)*val;//[L,R]一定是o對應區間的子區間,所以的更新o的和值
    if(T[o].l==T[o].r) return;
    if(L>=T[o*2+1].l) add(L,R,val,o*2+1);
    else if(R<=T[o*2].r) add(L,R,val,o*2);
    else{
        add(L,T[o*2].r,val,o*2);add(T[o*2+1].l,R,val,o*2+1);
    }
}

LL query(int L,int R,LL val,int o){
    if(T[o].l>=L && T[o].r<=R)  return T[o].s+(T[o].r-T[o].l+1)*(T[o].w+val);
    if(T[o].l==T[o].r) return 0;
    if(L>=T[o*2+1].l) return query(L,R,val+T[o].w,o*2+1);
    if(R<=T[o*2].r) return query(L,R,val+T[o].w,o*2);
    return query(L,T[o*2].r,val+T[o].w,o*2)+query(T[o*2+1].l,R,val+T[o].w,o*2+1);
}

int main(){
    //freopen("D:\\in.txt","r",stdin);
    while(cin>>N){
        cin>>Q;
        for(int i=1;i<=N;i++)
            scanf("%d",A+i);
        build(1,N,1);
        int a,b,c;char ch;
        while(Q--){
            getchar();
            scanf("%c",&ch);
            if(ch=='Q'){
                scanf("%d %d",&a,&b);
                printf("%lld\n",query(a,b,0,1));
            }else{
                scanf("%d %d %d",&a,&b,&c);
                add(a,b,c,1);
            }
        }
    }
    return 0;
}


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