POJ 3468 (线段树

线段树如果只进行自上而下的更新的话,并不必要把n扩大到2的幂,如果把自下而上的更新写成递归形式的话也不需要。

这题是经典的线段树应用,注意线段树的区间统一为左开右闭区间,没注意这个WA了几次

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#define INF 0x3fffffff
#define pb push_back
#define pn(x) cerr<<x<<endl

using namespace std;
typedef long long ll;
typedef pair<int,int> P;///num,pos
const int maxv=100005;

typedef pair<int,ll> node;
int N,Q;
int a[maxv];
ll data[maxv*4];////除了b以外其它的和,区间内
ll datb[maxv*4];/////区间内对每个数字加上的和
void init(int k,int l,int r){
    if(r-l==1){
        data[k]=a[l];
        return;
    }
    int chl=k*2+1,chr=k*2+2,m=(r+l)/2;
    init(chl,l,m);
    init(chr,m,r);
    data[k]=data[chl]+data[chr];
    return;
}
void update(int k,int c,int a,int b,int l,int r){
    if(a>=r||b<l) return;
    if(a<=l&&b>=r-1){
        datb[k]+=c;
        return;
    }
    data[k]+=c*(min(r,b+1)-max(a,l));
    int chl=k*2+1,chr=k*2+2,m=(r+l)/2;
    if(r-l>1){
        update(chl,c,a,b,l,m);
        update(chr,c,a,b,m,r);
    }
    return;
}
ll quary(int k,int a,int b,int l,int r){
    if(a>=r||b<l) return 0;
    if(a<=l&&b>=r-1) return data[k]+datb[k]*(min(r,b+1)-max(a,l));
    int chl=k*2+1,chr=k*2+2,m=(r+l)/2;
    ll ans=0;
    ans+=datb[k]*(min(r,b+1)-max(a,l));
    if(r-l>1){
        ans+=quary(chl,a,b,l,m);
        ans+=quary(chr,a,b,m,r);
    }
    return ans;
}
int main(){
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin>>N>>Q;
    for(int i=0;i<N;i++) scanf("%d",&a[i]);
    init(0,0,N);
    while(Q--){
        char q;
        cin>>q;
        if(q=='Q'){
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%I64d\n",quary(0,a-1,b-1,0,N));
        }
        else{
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            update(0,c,a-1,b-1,0,N);
        }
    }
    return 0;
}

 

posted @ 2015-05-06 17:50  PlusSeven  阅读(119)  评论(0)    收藏  举报