hdu 4348 主席樹

主席樹 區間更新。  好題目; 

又學會了一種方法。。  這種方法可以不寫push_down;

還有就是。。 這裏一定要提前建樹, 不然空間複雜度爲 (n+q)*logn 如果建樹爲n+ q*logn;

#include <bits/stdc++.h>
using namespace std;
int n,m;
const int MAXN = 4000010;
typedef long long ll;
ll sum[MAXN], lazy[MAXN];
int lc[MAXN], rc[MAXN],tot;
int root[MAXN];
void push_up(int i, int l, int r){
    sum[i] = sum[lc[i]] + sum[rc[i]] + (ll)(r - l+1) * lazy[i];
}
void build(int &i, int l, int r){
    i = ++tot;
    sum[i] = lazy[i] = lc[i] = rc[i] = 0;
    if(l == r){
        scanf("%lld", &sum[i]);
        return;
    }
    int mid = (l + r)>>1;
    build(lc[i], l, mid);
    build(rc[i], mid+1, r);
    push_up(i, l, r);
}
void insert(int pre, int &i, int l, int r, int L, int R, int val){
    i = ++tot;
    sum[i] = sum[pre], lc[i] = lc[pre], rc[i] = rc[pre], lazy[i] = lazy[pre];
    if( l == L && r == R){
        lazy[i] += val;
        sum[i] += (ll)val*(r - l + 1);
        return;
    }
    int mid = ( l + r ) >>1;
    if(L > mid) insert(rc[pre], rc[i], mid+1, r, L, R , val);
    else if(R <= mid) insert(lc[pre], lc[i], l, mid, L, R, val);
    else{
        insert(lc[pre], lc[i], l, mid, L, mid, val);
        insert(rc[pre], rc[i], mid+1, r, mid+1, R, val);
    }
    push_up(i, l, r);
}
ll query(int i, int l, int r, int L, int R, ll adv){
    if(l == L && r == R){
        return sum[i] + (ll)(adv)*(r - l + 1);
    }
    adv += lazy[i];
    int mid = (l + r) >> 1;
    if( L > mid ) return query(rc[i], mid+1, r, L, R, adv);
    else if( R<=mid) return query(lc[i], l, mid, L, R, adv);
    else{
        ll a = query(lc[i], l, mid, L, mid, adv);
        ll b = query(rc[i], mid+1, r, mid+1, R, adv);
        return a+b;
    }
}

int main(){
    while(cin>>n>>m){
        tot = 0;
        build(root[0], 1, n);
        char op[3];
        int x, y, z;
        int time = 0;
        while(m--){
            scanf("%s", op);
            if(op[0] == 'Q'){
                scanf("%d %d", &x, &y);
               printf("%I64d\n", query(root[time], 1, n, x, y, 0)); 
            }
            else if(op[0] == 'C'){
                scanf("%d %d %d", &x, &y, &z);
                time++;
                insert(root[time-1], root[time], 1, n, x, y, z);
            }
            else if(op[0] == 'H'){
                scanf("%d %d %d", &x, &y, &z);
                printf("%I64d\n", query(root[z], 1, n, x, y, 0));
            }
            else {
                scanf("%d", &time);
            }
        }
    }
    return 0;
}


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