8.4 Tree chain split

Detailed: https: //www.cnblogs.com/ivanovcraft/p/9019090.html

 

Essence tree is split chain sequence

In order to try to take the heavy chain, make possible a tree node decomposed into fewer chains collectively, as a continuous strand and the data structure is easily maintainable

 

The process has split twice dfs:

dfs1: find recrystallized point, establishing the depth of each point, the process may determine: sz [i], dep [i], fa [i], son [i]

void dfs1( int u ,int f ){
    sz[u] = 1;
    for( int i = head[u]; i ;i = edge[i].next ){
        int v = edge[i].to;
        if( v == f )continue;
        dep[v] = dep[u] + 1;
        fa[v] = u;
        dfs1( v ,u );
        sz[u] += sz[v];
        if( sz[v] >sz[ son[u] ] )son[u] = v;
    }
}

dfs2: heavy chain linked into the node (to identify top [i]), and the order of the link as a chain sequence present in the array (dfn [i]), the process may determine: dfn, top, rnk

void dfs2( int u ,int t ){
    dfn[u] = ++tot;
    top[u] = t;
    rnk[tot] = u;
    if( son[u] )dfs2( son[u] ,t );
    for( int i = head[u] ;i ;i = edge[i].next ){
        int v = edge[i].to;
        if( v!= fa[u] && v!= son[u] )dfs2(v,v);
    }
}

 

Split after the segment tree data structure may be utilized, and other Fenwick tree decomposition of the chain after maintenance, given two nodes x, y, update and query operations therebetween, this process is:

1. If x, y in a heavy chain (top [x] == top [y]), the data structure can be used directly x to y a contiguous chain that operate directly

2. If the x, y not on one heavy chain (top [x]! = Top [y]), find the deeper nodes (dep [fx]> dep [fy]) x, fx that the first x short operating, then let x transferred over its parent heavy chain

This process is repeated until the full path between the x y operation

This process is the process of finding x, y LCA's

int LCA( int x ,int y ){
    int fx = top[x] ,fy = top[y];
    while( fx != fy ){
        if( dep[x] < dep[y] )swap(x ,y) ,swap( fx ,fy );
        x= fa[fx] ,fx = top[x];
    }
    return dep[x] < dep[y] ? x : y ;
}
int c_query( int x ,int y ){
    int fx = top[x] ,fy = top[y];
    int ans = 0;
    while( fx != fy ){
        if( dep[fx] < dep[fy] )swap(x ,y) ,swap(fx ,fy);
        ans += query( 1 ,dfn[fx] ,dfn[x] );
        x = fa[x] ,fx = top[x];
    }
    if( x==y )return ans;
    if( dfn[x] > dfn[y] )swap( x ,y );
    if(dfn[x] != dfn[y])ans += query( 1 ,dfn[son[x]] ,dfn[y] );
    return ans ;
}

 


Segment tree: the tree-line on split chain code segment tree structure mostly written in the form of:

struct Tree{
    int left ,right;
    int t ,lazy;
}tree[N<<2];

Is this faster? I do not understand (the problem may never get to know me

 

Template question: HDU 3966 Aragorn's Story

Modify the interval, a single point of inquiry

I am useless in this segment tree structure also had to write

#include<bits/stdc++.h>

#define fi first
#define se second
#define rep( i ,x ,y ) for( int i= x; i<= y ;i++ )
#define reb( i ,y ,x ) for( int i= y; i>= x ;i-- )
#define mem( a ,x ) memset( a ,x ,sizeof(a))
#define lson  pos<<1 ,l ,m
#define rson  pos<<1|1 ,m+1 ,r
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int ,int> pii;
typedef pair<ll ,ll> pll;
typedef pair<string ,int> psi;

const int inf = 0x3f3f3f3f;
const int N = 50005;
const int M = 1000005;

struct Edge{
    int next ,to;
}edge[N<<2];
int sz[N] ,top[N] ,son[N] ,dep[N];
int fa[N] ,dfn[N] ,rnk[N];
int m ,n ,q ,tot = 0 ,cnt = 0 ,k;
int head[N] ;
ll val[N<<2] ,tree[N<<4] ,lazy[N<<4];

//线段树部分
void build( int pos ,int l ,int r ){
    if( l== r){
        tree[pos] = val[ rnk[l] ];
        return;
    }

    int m = (l+r)>>1;
    build ( rson );
    build ( lson );
    tree[pos] = tree[pos<<1]+tree[pos<<1|1];
    return;
}

void push_down( int pos ){
    int lc = pos<<1 ,rc = pos<<1|1 ;
    tree[lc] += lazy[pos];
    tree[rc] += lazy[pos];
    lazy[lc] += lazy[pos];
    lazy[rc] += lazy[pos];
    lazy[pos] = 0;
    return;
}

void updata( int pos ,int  l, int r ,int L ,int R ,int k ){
    //cout<<" updata "<<l<<" "<<r<<" "<<L<<" "<<R <<" "<<k<<endl;
    if( L<=l && r<=R ){
        lazy[pos] += k;
        tree[pos] += k;
        return;
    }

    int m = ( l+r )>>1;
    if( L <= m )updata( lson ,L ,R ,k);
    if( R > m )updata( rson ,L ,R ,k);
    tree[pos] = tree[pos>>1] + tree[pos>>1|1];
    return;
}

ll query( int pos ,int l ,int r ,int L ,int R ){
    //cout<<" query "<<l<<" "<<r<<" " <<L <<" "<<R<<endl;
    if( L<=l && r <= R ) return tree[pos];

    ll ans=0;
    push_down( pos );

    int m =( l+r )>>1;
    if( L <=m )ans += query( lson ,L ,R );
    if( R > m )ans += query( rson ,L ,R );
    return ans;
}

//树链剖分部分 --dfs1 ,dfs2 ,query ,updata
void dfs1( int u ,int rt ,int d ){
    //cout<<" dfs1 "<<u<<" "<<rt<<" dep "<<d<<endl;
    dep[u] = d;
    fa[u] = rt;
    sz[u] = 1;

    for( int i = head[u]; i ;i = edge[i].next ){
         int v =edge[i] .to;
         if( v == fa[u] )continue;
         dfs1( v ,u ,d+1 );
         sz[u] += sz[v];
         if( son[u] == 0 || sz[v] >sz[ son[u]]){
             son[u] = v;
         }
    }
    return ;
}

void dfs2( int u ,int t ){
    // u : now t :top
    //cout<<" dfs2 "<<u<<" "<<t<<" son "<<son[u]<<endl;
    top[u] = t;
    dfn[u] = ++cnt;
    rnk[cnt] = u;

    if( !son[u] ){
        return ;
    }
    dfs2( son[u] ,t );
    for( int i = head[u]; i ; i = edge[i].next ){
        int v=  edge[i].to;
        if( v == son[u] || v == fa[u] )continue;
        dfs2 (v, v);
    }
}

ll query_path( int x ,int y){
   ll ans = 0;
   int fx = top[x] ,fy = top[y];
   //cout<<" query_p "<<x <<" "<<y<<" "<<fx<<" "<<fy<<endl;
   while( fx != fy ){
          if(dep[fx] >= dep[fy] ){
                ans += query( 1 ,1 ,n ,dfn[fx] ,dfn[x] );
                x = fa[fx] ;
          }  else {
                ans += query( 1 ,y]);, N, Dfn [Fy], Dfn [1
                y = fa[fy];
          }
          fx = top[x] ,fy = top[y];
   }

   if(x != y ){
           if( dfn[x] < dfn[y] ){
               ans += query(1 ,1 ,n,dfn[x] ,dfn[y] );
           } else {
               ans += query(1 ,1 ,n,dfn[y] ,dfn[x] );
           }
   } else ans += query( 1 ,1 ,n,dfn[x] ,dfn[y] );
   return ans;
}

void updata_path( int x ,int y ,int z ){
    //cout<<x<<y<<z<<endl;
    int fx = top[x] ,fy = top[y];
    //cout<<" updata_p "<<x <<" "<<y<<" "<<fx<<" "<<fy<<endl;
    while( fx != fy ){
        if( dep[fx] >= dep[fy] ){
            updata( 1 ,1 ,n ,dfn[fx] ,dfn[x] ,z);
            x = fa[fx];1,1
            updata ({Else
        } ,n ,dfn[fy] ,dfn[y] ,z);
            y = fa[fy];
        }
        fx = top[x] ,fy = top[y];
    }

    if( x!=y ){
        if( dfn[x] < dfn[y] )updata( 1 ,1 ,n ,dfn[x] ,dfn[y] ,z );
        else updata( 1 ,1 ,n ,dfn[y] ,dfn[x] ,z );
    } else updata( 1 ,1 , n, dfn[x] ,dfn[y] ,z);
}


int main( ){
    while( ~ scanf("%d%d%d" ,&n ,&m ,&q) ){
        cnt = tot = 0;
        mem( son ,0 );
        mem( tree ,0);
        mem( lazy ,0);

        rep( i ,1 ,n )scanf("%lld" ,&val[i] ) ,head[i] = edge[i].next = 0;
        int l ,r;
        while( m-- ){
            scanf("%d%d" ,&l ,&r );
            edge[++tot].next = head[l];
            edge[tot].to = r;
            head[l] = tot;

            edge[++tot].next = head[r];
            edge[tot].to = l;
            head[r] = tot;
        }

        dfs1( 1 ,1 ,0 );
        dfs2( 1 ,1 );
        build(1, 1 ,n );
        char op;
        while ( q--){
            //cout<<q<<endl;

            cin>>op;
            if( op == 'I' ){
                scanf("%d%d%d" ,&l ,&r ,&k);
                updata_path( l ,r ,k );
            }
            if( op == 'Q' ){
                scanf("%d" ,&l );
                printf("%lld\n" ,query(1 ,1 ,n ,dfn[ l ] ,dfn[ l ] ) );
            }
            if( op == 'D' ){
                scanf("%d%d%d" ,&l ,&r ,&to);
                //cout<<l<<" "<<r<<" "<<k<<endl;
                updata_path( l ,r ,-k );
            }
        }
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/-ifrush/p/11298274.html