【树上前缀和】

【树上前缀和】

Compare Tree Weights

【树链剖分+树状数组维护顶点前缀和】
https://atcoder.jp/contests/abc406/tasks/abc406_f

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef pair<int,int> PII;
typedef long long ll;
ll abss(ll a){return a>0?a:-a;}
ll max_(ll a,ll b){return a>b?a:b;}
ll min_(ll a,ll b){return a<b?a:b;}
bool cmpll(ll a,ll b){return a>b;}
const int N=3e5+10;
/*注意这题的下标索引*/
struct FenwickTree {
      vector<int> tree;
      int size;
      FenwickTree(int n){
            size=n;
            tree.resize(n+1,0);
      }
      void update(int pos, int delta){
            pos++;//转成1-based索引
            for(;pos<=size;pos+=pos&-pos)
                  tree[pos]+=delta;
      }
      int query(int pos){
            pos++;//转成1-based索引
            int res=0;
            for(;pos>0;pos-=pos&-pos)
                  res+=tree[pos];
            return res;
      }
      int rangeQuery(int l, int r){
            return query(r)-query(l-1);
      }
};
int n;
int u[N],v[N];
vector<int> g[N];
//dfs序
int l_idx[N],r_idx[N];
//求dfs序:从1开始
int cur=0;
void dfs(int u){
    l_idx[u]=cur;
    cur++;
    for(auto son:g[u]) if(l_idx[son]==-1) dfs(son);
    r_idx[u]=cur;
    return;
}
void solve(){
    cin>>n;
    FenwickTree fw(n);
    for(int i=1;i<n;i++){
        cin>>u[i]>>v[i];
        u[i]--;v[i]--;
        g[u[i]].push_back(v[i]);
        g[v[i]].push_back(u[i]);
    }
    memset(l_idx,-1,sizeof(l_idx));
    memset(r_idx,-1,sizeof(r_idx));

    dfs(0);
    /*
    for(int i=0;i<n;i++){
        cout<<l_idx[i]<<" "<<r_idx[i]<<endl;
    }
    */
    for(int i=0;i<n;i++){
        fw.update(i,1);
    }
    /*
    for(int i=1;i<=n;i++){
        cout<<fw.query(i)<<endl;
    }
    */
    int sum=n;//当前总和
    int q;
    cin>>q;
    while(q--){
        int op;
        cin>>op;
        if(op==1){
            int x,w;
            cin>>x>>w;
            x--;
            fw.update(l_idx[x],w);
            sum+=w;
        }
        else if(op==2){
            int y;
            cin>>y;
            //找儿子:dfs l_idx大的那一个
            int son=u[y];
            if(l_idx[u[y]]<l_idx[v[y]]) son=v[y];
            else son=u[y];
            int ans=abs(2*fw.rangeQuery(l_idx[son],r_idx[son]-1)-sum);
            cout<<ans<<endl;
        }
    }
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--) solve();
    return 0;
}
posted @ 2025-05-18 07:59  White_ink  阅读(15)  评论(0)    收藏  举报