P3833 [SHOI2012] magic tree (the tree split chain template title)

Topic links: https://www.luogu.org/problem/P3833

Title effect: a containing tree has n nodes, each node is initially 0, the following two operations:

1.Add uvd represents the value of all the nodes on the path between u and v are plus d.

2.Query u represents the current fruit trees, to the point u rooted sub-tree, the fruit of a total of how many?

 

Outline of Solution: chain split tree board, particularly to see code comments

Code:

#include <bits / STDC ++ H.>
 the using  namespace STD; 
typedef Long  Long LL;
 const  int MAXN = 100005 ;
 int TOT, CNT, head [MAXN], n-, m, V [MAXN]; 
LL Tree [MAXN * . 4 ] , the lazy [* MAXN . 4 ];
 int D [MAXN], size [MAXN], Son [MAXN], ID [MAXN], RK [MAXN], FA [MAXN], Top [MAXN];
 // size [I] is the number of nodes of subtree i, top [i] where i is the top of the heavy chain, son [i] is the number of heavy son i
 // D [i] is the true depth of the node i, id [i] is the i the new number, fa [i] is the number i father 
struct Edge {
     int V, Next; 
} Edge [MAXN << . 1 ];
 void the Add (int U, int V) { 
    Edge [TOT] .v = V; 
    Edge [TOT] .next = head [U]; 
    head [U] = TOT ++ ; 
} 
void DFS1 ( int U, int pre) { // first dfs seeking over a depth of each node, a parent node, the size of the subtrees where 
    D [U] = D [pre] + . 1 ; 
    FA [U] = pre; 
    size [U] = . 1 ;
     for ( int I = head [U ];! = I - . 1 ; I = Edge [I] .next) {
         int V = Edge [I] .v;
         IF (V =! pre) {
            DFS1 (V, U); 
            size [U] + = size [V];
             IF (size [Son [U]] <size [V]) Son [U] = V; 
        } 
    } 
} 
void DFS2 ( int U, int TP) { // find each new node number and weight of the heavy chain where the top and son 
    top [U] = TP, ID [U] = CNT ++, RK [CNT] = U;
     IF (son [U]) DFS2 (son [U], TP); 
     // start and re-son node dfs order to ensure that all nodes on a continuous heavy chain to heavy chain may be maintained by a segment tree information 
    for ( int I = head [U]; I ! = - . 1 ; I = Edge [I] .next) {
         int V = Edge [I] .v;
         IF (V FA = [U] = V &&!!son[u]) dfs2(v,v);
    }
}
void pushup(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdown(int l,int r,int rt){
    if(lazy[rt]){
        tree[rt<<1]=tree[rt<<1]+lazy[rt]*l;
        tree[rt<<1|1]=tree[rt<<1|1]+lazy[rt]*r;
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void build(int l,int r,int rt){
    lazy[rt]=0;
    if(l==r){
        tree[rt]=v[rk[l]];
        return;
    }
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
void update(int L,int R,int val,int l,int r,int rt){
    if(L<=l&&R>=r){
        tree[rt]+=1ll*(r-l+1)*val;
        lazy[rt]+=val;
        return;
    }
    int mid=l+r>>1;
    pushdown(mid-l+1,r-mid,rt);
    if(mid>=L) update(L,R,val,l,mid,rt<<1);
    if(mid<R) update(L,R,val,mid+1,r,rt<<1|1);
    pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
    if(L<=l&&R>=r) return tree[rt];
    int mid=l+r>>1; ll res=0;
    pushdown(mid-l+1,r-mid,rt);
    if(mid>=L) res+=query(L,R,l,mid,rt<<1);
    IF (MID <R & lt) RES + = Query (L, R & lt, MID + . 1 , R & lt, RT << . 1 | . 1 );
     return RES; 
} 
void Updates ( int x, int y, int Val) { // Modify x to y value of the shortest path 
    the while (Top [X]! = Top [Y]) { // not the same heavy chain to jump up 
        IF (D [Top [X]] < D [Top [Y]]) the swap (X, Y); 
        Update (ID [top [X]], ID [X], Val, . 1 , n-, . 1 ); 
        X = FA [top [X]]; // jump to the top of the heavy chain of the parent node 
    }
     IF (ID [X]> ID [Y]) the swap (X, Y); //Two nodes in the same heavy chain, but may not be the same node 
    Update (ID [X], ID [Y], Val, . 1 , n-, . 1 ); 
} 
LL ASK ( int X, int Y) { // query x to y shortest path value 
    LL RES = 0 ;
     the while (! Top [x] = Top [y]) {
         IF (D [Top [x]] < D [Top [y]]) the swap (x, y) ; 
        RES + = Query (ID [Top [X]], ID [X], . 1 , n-, . 1 ); 
        X = FA [Top [X]]; 
    } 
    IF (ID [X]> ID [Y]) the swap (X, Y); 
    RES + = Query (ID [X], ID [Y], . 1 , n-, . 1);
    return res;
}
int main(){
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        u++; v++;
        add(u,v);
    }
    scanf("%d",&m);
    cnt=0,tot=0;
    dfs1(1,0),dfs2(1,1);
    build(1,n,1);
    while(m--){
        char op[10];
        int l,r,rt,val;
        scanf("%s",op);
        if(op[0]=='A'){
            scanf("%d%d%d",&l,&r,&val);
            l++; r++;
            Updates (L, R & lt, Val); 
        } the else { 
            Scanf ( " % D " , & RT); RT ++ ; 
            the printf ( " % LLD \ n- " , Query (ID [RT], ID [RT] + size [RT] - . 1 , . 1 , n-, . 1 ));
             // since the size of a sub-tree is the size [rt], the starting point is a number from id [rt] so from id [rt] to id [rt] + size [rt ] - . 1 
        } 
    } 
    return  0 ; 
}

 

Guess you like

Origin www.cnblogs.com/zjl192628928/p/11298733.html