[Notes] long chain split

nature

Property 1: long-chain split tree, the tree and all the long chain length and is \ (n-\)

Property 2: For any point tree \ (X \) , its \ (K \) level ancestor \ (Y \) length where the long-chain constant \ (\ GE K \) .

Nature 3: Root jump upwardly from any point of a side through which light does not exceed \ (\ sqrt n \) Article

Scope:

1. The sub-tree maintenance information related only to the depth, \ (O (the n-) \) statistics for each point in the tree can be combined with the next target depth information.

2. Single \ (O (1) \) online query a point \ (k \) level ancestors.

achieve:

Subtree split according to depths, the deepest depth of the chain together into son

Son with respect to heavy \ (O (1) \) inheritance information of the time, the light directly change his son

inline void dfs1(re int x,re int prt,re int depth){
    re int i,y;maxd[x]=dep[x]=depth;fa[x]=prt;size[x]=1;
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;if(y==prt)continue;
        dfs1(y,x,depth+1);size[x]+=size[y];
        if(maxd[y]>maxd[x]){maxd[x]=maxd[y];son[x]=y;}
    }
}
inline void dfs2(re int x,re int Top){
    re int i,y;top[x]=Top;st[x]=++tot;
    if(!son[x])return;
    dfs2(son[x],Top);
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;if(y==prt||y==son[x])continue;
        dfs(y,y);
    }
}

use:

1. \ (O (. 1) \) seeking \ (K \) level ancestor

The first step pretreatment

  • \ (ST \) preprocessing each point of the \ (2 ^ K \) level ancestor
  • For all (K (. 1-n-) \) \ , we put this \ (K \) is converted into binary representation, which records the number of bits \ (log_K \)
    apparently \ (2log_K \ geq \ frac { K} {2 } \)
  • Set \ (len_x \) nodes \ (X \) long chain length belongs, to the end nodes of all long chain \ (TP \) , we record \ (TP \) above and below the \ (len_ {tp} - 1 \) node.
void dfs1(re int x,re int prt,re int depth){
    re int i,y;
    *dp[x]=prt;maxd[x]=dep[x]=depth;
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;if(y==prt)continue;
        dfs1(y,x,depth+1);
        if(maxd[x]<maxd[y]){maxd[x]=maxd[y];son[x]=y;}
    }
}
void dfs2(re int x,re int Top){
    re int i,y;top[x]=Top;
    len[x]=maxd[x]-dep[Top]+1;
    if(!son[x])return;
    dfs2(son[x],Top);
    for(i=h[x];i;i=e[i].next){y=e[i].to;if(y==*dp[x]||y==son[x])continue;dfs2(y,y);}
}
inline void ST(void){
    re int i,j;
    for(j=1;j<=18;++j)
        for(i=1;i<=n;++i)dp[i][j]=dp[dp[i][j-1]][j-1];
    *tot=-1;for(i=1;i<=n;++i)tot[i]=tot[i>>1]+1;
}
inline int LCA(re int x,re int y){
    re int i;
    if(dep[x]<dep[y])swap(x,y);
    for(i=18;~i;--i)if(dep[dp[x][i]]>=dep[y])x=dp[x][i];
    if(x==y)return x;
    for(i=18;~i;--i)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}
    return *dp[x];
}
inline void Inc(void){
    re int i,j,tp,sum,tmp;sum=0;
    for(i=1;i<=n;++i){
        tp=top[i];if(vis[tp])continue;vis[tp]=1;
        idx[tp]=sum+len[tp];save[idx[tp]]=tp;
        tmp=tp;for(j=idx[tp]-1;j>idx[tp]-len[tp];--j){tmp=son[tmp];save[j]=tmp;}
        tmp=tp;for(j=idx[tp]+1;j<idx[tp]+len[tp];++j){tmp=*dp[tmp];save[j]=tmp;}
        sum+=2*len[tp]-1;
    }
} 

Then handles inquiries:

The inquiry set point is \ (the X-\) , looking for its \ (K \) level ancestor \ (fa \)

Firstly \ (ST \) from the interrogation points \ (X \) hop on \ (2 ^ {log_K} \ ) step, after this point is called the hop \ (Y \) .

Since then \ (2 ^ {log_K} \ geq \ FRAC {K} {2} \) , we jumped at least \ (K \ over 2 \) steps.

At this time, depending on the nature \ (2 \) , \ (Y \) the length of a long chain where \ (len_y \ GEQ \ K FRAC} {2} {\) .

Set \ (TP \) of \ (Y \) to the top node is located in a long chain.

At \ (TP \) of the above \ ((K-2 ^ { log_K}) - Dis (y, tp) \) points. (A negative number is below \ (0 \) is \ (tp \) itself)

} 
inline int Query(re int x,re int k){
    re int tp;if(k>dep[x])return 0;if(!k)return x;
    x=dp[x][tot[k]];k-=1<<tot[k];
    tp=top[x];return save[idx[tp]+k-(dep[x]-dep[tp])];  
}

Template title

\(BSOJ5187\)or\(BSOJ5385\)

Since \ (k \) of uncertain size, so do the points situation. Set \ (Lim = \ n-sqrt {} \) , when the \ (k \ le Lim \) when the pretreatment can \ (sum [i] [j ] \) represents \ (I \) nodes \ (J \) pace has been going up, I walked up to the root ( \ (i \) node depth if not \ (k \) multiple of the root node is not included) can get up to a point and the right to directly ask the query just fine. when \ (k> Lim \) , the violence will go up with a long chain split (O (1) \) \ query a grade point k ancestors, so climb up to \ (\ sqrt { n} \) times;

Single query time complexity \ (O (\ n-sqrt {}) \) .

2. \ (O (the n-) \) inherit Information Optimization \ (dp \)

\(BSOJ6308\)

We first expressed what they require, we try to put into \ (x \) distance \ (\ leq k \) the right point and into the in \ (x \) to the sub-tree \ (x \) distance \ (\ leq k \) points right and

Set \ (\ displaystyle {f_ {x , k}} \) represents the \ (X \) to a subtree \ (X \) distance \ (\ leq k \) the right point and

\ (fa ^ x_k represent \) the X- \ (a \) k $-class father

\(\displaystyle{Ans_{x,K}=f_{x,K}+\sum_{k=1}^{\min{\{dep_x,K\}}}f_{fa^x_k,K-k}-f_{x,K-2k}}\)

The latter is for every \ (x \) is \ (k \) class father, we find in its sub-tree but not in the \ (x \) sub-tree, from which \ (Kk \) from the right point and

Thus it is equivalent to, in \ (X \) above from \ (X \) does not exceed \ (K \) distance and

This question is concerned with how to use long-chain split

In order to \ (O (n) \) to complete the re-son inheritance, we put it another try

New \ (f_ {id_x + k} \) represents \ (X \) within a sub-tree is no more than \ (K \) the right point and

Such features what good is it for \ (X \) heavy son \ (Y \) , \ (F_ {id_x + K} = F _ {(id_y +. 1) + K} = F_ {id_y + (K +. 1) } \) , do not assign it inherited from the information below

Analysis can then be transferred, posted about teacher

After re-direct successor son finished:

\(j=0,f_{id_x}=a_x\)

\(1\leq j\leq len_x,f_{id_x+j}+=a_x\)

Set light to his son \ (the y-\) , \ (the X-\) point with a weight of \ (a_x \) , pay attention to judge for themselves when violence maintenance \ (j \) and \ (len_y \) size

\(1\leq j\leq len_{y}+1,则f_{id_x+j}+=f_{id_y+j-1}\)

\ (Len_ {s} + 2 \ leq j \ leq len_ {x}, {f_ 则 id_x + j} = + + f_ {id_y len_ {y}} \)

\ (Modify form: \)

\(1\leq j\leq len_{y}+1,则f_{id_x+j}+=f_{id_y+j-1}-f_{id_y+len_{y}};\)

\(1\leq j\leq len_{x},则f_{id_x+j}+=f_{id_y+len_{y}}\)

Circulating heavy chain needs to be optimized out:

\ (The f_ {id_y + leny} accumulated in sum_ {id_x} \)

\(1\leq j\leq len_{y}+1,则f_{id_x+j}+=f_{id_y+j-1}-f_{id_y+len_{y}};\)

\(sum_{id_x}+=f_{id_y+len_{y}}\)

\ (Due f_ {id_x + 0} does not need to accumulate sum_ {id_x}, it is necessary to advance subtracted, then \)

\(f_{id_x}-=-sum_{id_x}\)

\(sum_{id_x}+=w_{x}\)

\(0\leq j\leq len_{x},f_{id_x+j}+=sum_{id_x}\)

\ (Now try to optimize away the last of the heavy chain cycle (because violence can only maintain the light chain, the heavy chain of violence will change the maintenance time complexity): \)

\ (Actually only needed when using the f array and sum array package, do not need to sum each array is added to the result f the array, in which case equivalent to the original sum f and f split into two parts Note that at this time when heavy son inherited directly over f, sum did not come directly inherited, so now in addition to inheriting the sum \)

\ (F heavy son array directly inherited, sum array now need to inherit a separate \)

\(sum_{id_x}=sum_{id_{son_{x}}}\)

\(1\leq j\leq len_{y}+1,则f_{id_x+j}+=f_{id_y+j-1}+sum_{id_y}-f_{id_y+leny}-sum_{id_y};\)

\ (F originally all uses have become f + sum \)

\(sum_{id_x}+=f_{id_y+leny}+sum_{id_y}\)

\(f_{id_x}-=sum_{id_x}\)

\(sum_{id_x}+=w_{x}\)

\ (While using f_ {id_x + k} + sum_ {id_x} updating answer to \)

inline void Solve(re int x){
    re int i,j,y,leny;if(son[x]){Solve(son[x]);sum[idx[x]]=sum[idx[son[x]]];}
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;
        if(y==fa[x]||y==son[x])continue;
        Solve(y);leny=maxd[y]-dep[y];
        for(j=1;j<=leny+1;++j)dp[idx[x]+j]+=dp[idx[y]+j-1]+sum[idx[y]]-(dp[idx[y]+leny]+sum[idx[y]]);
        sum[idx[x]]+=dp[idx[y]+leny]+sum[idx[y]];
    }
    dp[idx[x]]-=sum[idx[x]];sum[idx[x]]+=a[x];
    for(i=hq[x];i;i=eq[i].next){
        y=eq[i].to;
        ans[y]+=eq[i].opt*(sum[idx[x]]+dp[min(1ll*idx[x]+eq[i].k,1ll*idx[x]+maxd[x]-dep[x])]);
    }
}

Guess you like

Origin www.cnblogs.com/66t6/p/11707687.html