hdu3966-樹刨+bit區間修改單點查詢

題意:對樹上兩點區間增加或減少每點的權值,單點查詢每點的權值。
思路:一開始線段樹寫的,但是我的被卡了2*maxn的空間,優化一下就可以了,但是嫌太麻煩,出題人可能就打算卡部分人的線段樹。
用bit的話,類似預處理數組,每次查詢0-x點的區間和就可以,修改左端點和右端點的權值爲v和-v即可。
代碼:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
const int maxn = 5e4+5;
int n,m,id,q,top[maxn],a[maxn],p[maxn],par[maxn],son[maxn],sz[maxn],deep[maxn];
vector<int>e[maxn];
struct BIT{
    int node[maxn];
    int lb(int x){return x&(-x);}
    void init(){forn(i,maxn)node[i] = 0;}
    void update(int pos,int v){for(int i = pos;i<=n;i+=lb(i))node[i]+=v;}
    int ask(int pos){int sum = 0;for(int i = pos;i;i-=lb(i))sum+=node[i];return sum;} 
}bit;
void init(){
    forn(i,maxn){
        son[i] = 0;
        e[i].clear();
    }
    bit.init();
    id = 0;
}
void dfs(int u,int pre,int d){
    sz[u] = 1,par[u] = pre,deep[u] = d;
    for(auto v:e[u])if(v!=pre){
        dfs(v,u,d+1);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u] = v;
    }
}
void getpos(int u,int gg){
    top[u] = gg,p[u] = ++id;
    if(son[u]) getpos(son[u],gg);
    for(auto v:e[u])if(v!=par[u]&&v!=son[u]){
        getpos(v,v);
    }
}
void change(int x,int y,int v){
    int fx = top[x],fy = top[y];
    while(fx!=fy){
        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);
        bit.update(p[fx],v);
        bit.update(p[x]+1,-v);
        x = par[fx],fx = top[x];
    }
    if(deep[x]>deep[y]) swap(x,y);
    //cerr<<x<<' '<<p[x]<<' '<<v<<'\n';
    bit.update(p[x],v);
    bit.update(p[y]+1,-v);
}
int main(){
    IO;
    while(cin>>n>>m>>q){
        init();
        for1(i,n) cin>>a[i];
        forn(i,m){
            int x,y;cin>>x>>y;
            e[x].push_back(y);
            e[y].push_back(x);
        }
        dfs(1,0,0);
        getpos(1,1);
        for1(i,n){
            bit.update(p[i],a[i]);
            bit.update(p[i]+1,-a[i]);
        }
        while(q--){
            char c;cin>>c;
            if(c=='Q'){
                int x;cin>>x;   
                cout<<bit.ask(p[x])<<'\n';
            }else{  
                int x,y,z;cin>>x>>y>>z;
                if(c=='D') z = -z;
                change(x,y,z);
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章