chain sequence and split tree dfs

chain sequence and split tree dfs

to sum up

  • dfs tree sequence and the chain split is linearly mapped into a tree structure, for example, then such a segment tree data structure to maintain information section
  • Sequence dfs dfs node tree is arranged to generate a new number, the advantage that the number of each tree / subtrees is continuous, so can easily be modified to any subtree
  • Chain split tree is a kind of a heavy chain / heavy side as dfs first traversal, so that not only can be modified for any subtree, but also simple tree path between two nodes easily modify. The latter operation is each modification (update interval) Top [] deeper heavy chain, such that the final two nodes on a heavy chain, and then modify the heavy chain.
    Due to the limited number needs to be modified heavy chain (without proof is given \ (logN \) ), so that each operation complexity \ (O ({logn} ^ 2) \)

The basic steps

  1. The first dfs, pre-out tree size, node height, weight son, father node
  2. The second DFS, to re-prioritize edge DFS, renumbering, while the heavy chain of processing nodes Top [] nodes (nodes of the head of the heavy chain)
  3. Segment tree maintenance can be

    reference

    blog0

Template title

template

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db(x) cout<<"["<<#x<<"]="<<x<<endl
const ll maxn=1e6+10;
ll N,M;
ll seg[maxn],lazy[maxn];
ll a[maxn],b[maxn];
ll dep[maxn],sz[maxn],son[maxn],fa[maxn];//for dfs1
ll top[maxn],idx[maxn];// for dfs2
vector<ll> G[maxn];
ll tot;//用于重编号
ll dfs1(ll now,ll fath,ll depth){
    dep[now]  =depth;
    sz[now] = 1;
    fa[now] = fath;
    ll maxson = -1;
    for(ll i=0;i<G[now].size();i++){
        ll v = G[now][i];
        if(v==fath) continue; //continue 写法不易出错
        sz[now]+=dfs1(v,now,depth+1);
        if(sz[v]>maxson){maxson = sz[v];son[now] = v;}
    }
    return sz[now];
}
void dfs2(ll now,ll topf){
    idx[now] = (++tot);
    b[tot] = a[now];//
    top[now] = topf;
    if(!son[now])return ;
    dfs2(son[now],topf);
    for(ll i=0;i<G[now].size();i++){
        ll v = G[now][i];
        if(!idx[v]) dfs2(v,v);
    }

}
void build(ll root,ll l,ll r){
    if(l==r){
        seg[root] = b[l];
        return ;
    }
    ll mid = (l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    seg[root] = seg[root<<1]+seg[root<<1|1];
}
void push_down(ll root,ll l,ll r){
    if(lazy[root]){
        ll mid = (l+r)>>1;
        seg[root<<1] += (mid-l+1)*lazy[root];
        seg[root<<1|1]+=(r-mid)*lazy[root];
        lazy[root<<1] +=lazy[root];
        lazy[root<<1|1]+=lazy[root];
        lazy[root]=0;
    }
}
void pointAdd(ll root,ll l,ll r,ll pos,ll val){
    if(l==r){
        seg[root]+=val; return ;
    }
    push_down(root,l,r);
    ll mid = (l+r)>>1;
    if(pos<=mid) pointAdd(root<<1,l,mid,pos,val);
    else pointAdd(root<<1|1,mid+1,r,pos,val);
    seg[root] = seg[root<<1]+seg[root<<1|1];
}
void intervalAdd(ll root,ll l,ll r,ll x,ll y,ll val){
    if(x<=l&&r<=y){
        seg[root]+=val*(r-l+1);
        lazy[root]+=val;
        return ;
    }
    push_down(root,l,r);
    ll mid = (l+r)>>1;
    if(x<=mid) intervalAdd(root<<1,l,mid,x,y,val);
    if(y>mid) intervalAdd(root<<1|1,mid+1,r,x,y,val);
    seg[root] = seg[root<<1]+seg[root<<1|1];
}
ll intervalAsk(ll root,ll l, ll r,ll x,ll y){
    if(x<=l&&r<=y){
        return seg[root];
    }
    push_down(root,l,r);
    ll mid = (l+r)>>1;
    ll ans = 0;
    if(x<=mid) ans+=intervalAsk(root<<1,l,mid,x,y);
    if(y>mid) ans+=intervalAsk(root<<1|1,mid+1,r,x,y);
    return ans;
    
}
ll treeSum(ll x,ll y){
    ll ans = 0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ll t=intervalAsk(1,1,N,idx[top[x]],idx[x]);
        ans+=t;
        x = fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans+=intervalAsk(1,1,N,idx[x],idx[y]);
    return ans;
}
int main(){
    scanf("%lld %lld",&N,&M);
    for(ll i=1;i<=N;i++)scanf("%lld",a+i);
    for(ll i=1;i<N;i++){
        ll u,v;
        scanf("%lld %lld",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,0,1);dfs2(1,1);
    build(1,1,N);
    while(M--){
        ll op,x,val;
        scanf("%lld",&op);
        if(op==1){
            scanf("%lld %lld",&x,&val);
            pointAdd(1,1,N,idx[x],val);
        }
        else if(op==2){
            scanf("%lld %lld",&x,&val);
            intervalAdd(1,1,N,idx[x],idx[x]+sz[x]-1,val);
        }
        else{
            scanf("%lld",&x);
            printf("%lld\n",treeSum(1,x));
        }

    }
}

Guess you like

Origin www.cnblogs.com/fridayfang/p/11097151.html