A tree difference title set

 

 

 

A tree difference

 

Codeforces - 739b  Alyona and A Tree (differential binary tree +)

Subject to the effect:

To the tree, the root of the tree is a set of weighted 1, the trees each point a little right, and the right side as well. Now given "control" is defined: for a point u, v provided for the sub-tree nodes, and $ dis (u, v) ≤val [v] $, u is said control v. The number of points obtained for each control point.

Problem-solving analysis:

Process all the points to the root from $ dist $, then the distance between any two points is $ dist [v] -dist [u] $ ($ v $ $ U $ is the subtree node). Because on each strand, $ dist search process by the root depth in the subtree is incremented $, it is possible to quickly find the most shallow $ $ DEP parent node of the current node can be controlled with diethyl points, and then use a tree difference efficient number of statistics.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x){        
    x=0;int f=1;char ch=getchar();
    while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
    while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
    x*=f;
}
#define REP(i,s,t) for(int i=s;i<=t;i++)
#define fi first
#define se second
#define pb push_back
typedef long long ll;
const int N = 2e5+5;
int n,m,cnt,loc[N];
ll val[N],dist[N],sum[N],dfn[N];
typedef pair<int,ll>P;
vector<P>G [N];
 // SUM [I] represents the number of nodes of each point can be governed 
void DFS ( int U) { 
    DFN [ ++ CNT] = dist [U]; LOC [CNT] = U;
     int CUR = lower_bound (DFN + . 1 , DFN + . 1 + CNT, dist [U] -Val [U]) - DFN; // dist [V] -dist [U] <= Val [V] ===> dist [V] -Val [ V] <= dist [U]        // find this point can be governed shallowest ancestor node 
    SUM [LOC [cur . 1 ]] - ;
     for (Auto & E: G [U]) {
         int V = E .fi; LL = cost e.se; 
        dist [V] = dist [U] + cost; 
        DFS (V); 
        SUM [U] + = SUM [V] + . 1; 
    }
     --Cnt;     // delete all this chain branch point 
}
 int main () { 
    Read (n-); 
    REP (I, . 1 , n-) Read (Val [I]); 
    REP (I, 2 , n-) {
         int U, W; Read (U); Read (W); 
        G [U] .pb (P (I, (LL) W)); 
    } 
    DFS ( . 1 ); 
    REP (I, . 1 , n-) the printf ( " % LLD " , SUM [I]); 
}
View Code

 

 

 

 

BZOJ - 4326  NOIP2015 transportation plan (half a tree difference + answer + LCA)

Title effect:
to the n dots and m transportation plan tree (s → t), the time to complete all the transportation schedule is planned maximum transport time. Now we can put the right edge of one side to 0, find the fastest time to complete all transport plans.
Problem-solving analysis:
see the problem of minimizing the maximum, you should expect half the answer. The main question is the difficulty dichotomy check, need to use a tree difference to check, but this question a tree difference of ideas is not difficult, mainly for statistical purposes, in a sub-tree, how many to enumerate a maximum distance of more than half one of the nodes in which the distance (between the piece so as to root node to the sub-tree by removing the root side to shorten the distance between nodes query). This is mainly to remove the root of this edge between the sub-tree root node enumeration of this idea is more difficult now. Because only allowed to delete an edge, so this sub-process is quite wonderful.

#include <bits/stdc++.h>
using namespace std;
template<typename T>inline void rd(T&x){
    x=0;int f=1;char ch=getchar();
    while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
    while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
    x*=f;
}
#define bug cout<<"NO bug!\n";
#define debug(x) cout<<#x<<" "<<x<<"\n";
#define clr(a,b) memset(a,b,sizeof(a))
#define RP(i,s,t) for(int i=s;i<=t;i++)
#define rp(i,s,t) for(int i=s;i<t;i++)
const int N = 3e5+5 , MAV = 20;
int f[N][MAV],n,m,cnt,head[N],dep[N],val[N],dis[N],lca[N],sum[N],dist[N];

struct Edge{ int from,to,w,nxt; }e[N<<1];
 
struct the Ask { int U, V;} Q [N]; 

inline void the Add ( int U, int V, int W) { 
    E [ ++ CNT] = (Edge) {U, V, W, head [U]} ; head [U] = CNT; 
} 
void the DFS ( int U, int pre) {     // treated to give the father and each depth of each node, and each node from the root node 
    for ( int I = head [U]; I; I = E [I] .nxt) {
         int v = E [I] .to;
         IF ! (v = pre)         // F [v] [0] represents the parent node v                 //The most important is Val [v], is recorded, the direction of the right side down to the root of v, i.e. each node toward a side nearer to the right side of the root, has far-reaching effects in the check () when 
            F [V] [ 0 ] = U, DEP [V] DEP = [U] + . 1 , DIS [V] = DIS [U] + (Val [V] = E [I] .W), the DFS (V, U); 
    } 
} 
void initST () {             // initialization st table 
    RP (J, . 1 , the MAV) the RP (I, . 1 , n-) { 
        F [I] [J] = F [F [I] [J- . 1 ]] [J- . 1 ]; 
    } 
} 
int the LCA ( int X, int Y) {     // get any two points of the LCA 
    IF (DEP [X] < DEP [Y]) the swap (X, Y);
     for ( int j=MAV-1;j>=0;j--)
        if(dep[x]-(1<<j)>=dep[y])x=f[x][j];
    if(x==y)return x;
    for(int j=MAV-1;j>=0;j--)
        if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
    return f[x][0];
}
void Count(int u,int pre){            //统计每颗子树的sum值
    for(int i=head[u];i;i=E [I] .nxt) {
         int V = E [I] .to;
         IF (V == pre) Continue ; 
        the Count (V, U); 
        SUM [U] + = SUM [V]; 
    } 
} 
BOOL Check ( int X) {         // a difference to verify the tree 
    CLR (SUM, 0 );
     int MX = 0 , NUM = 0 ; 
    the RP (I, . 1 , m) {
         int U = Q [I] .u, V = Q [I] .v;         // note to -2 at lca, because if two nodes in the same sub-tree, then to remove the root of the subtree root side, and does not reduce the nodes between the two from 
        IF SUM (dist [I]> X) [U] ++, SUM [V] ++, SUM [LCA [I]] - = 2, NUM ++, MX = max (MX, dist [I] the -X-);    // MX records in all transport more than the maximum time x 
    } 
    the Count ( . 1 , - . 1 );         // count the sum value of all subtrees 
    RP (I, 2 , n-) IF (SUM [I] == && Val NUM [I]> = MX) return  to true ; // if there is a subtree which contains all of the longest distance is longer than the current node enumeration and the direction of the root node to the root node of the subtree right side of this edge is larger than mx, you can pass the right side of these edges is set to 0, indicating that the current is enumerated longest distance possible 
    return  to false ; 
} 
int main () { 
    RD (n-); RD (m); 
    RP (I, . 1 , n-) {
         int U, V, W; RD (U); RD (V); RD (W); 
        the Add ( U, V, W); the Add (V, U, W); 
    } 
    the RP (I,. 1 , m) {
         int U, V; RD (U); RD (V); 
        Q [I] = (the Ask) {U, V}; 
    } 
    the DFS ( . 1 , - . 1 ); initST ();
     int L = 0 , R & lt = 0 ; 
    the RP (I, . 1 , m) {
         int U = Q [I] .u, V = Q [I] .v; 
        LCA [I] = the LCA (U, V); R & lt = max ( R & lt, (dist [I] = DIS [U] DIS + [V] - 2 * DIS [LCA [I]]));             // dist represents a distance between corresponding points 
    }
     int ANS = 0 ;
     the while (L <= R & lt) {             // binary answer, the smallest maximum distance enumeration 
        int mid=l+r>>1;
        if(check(mid))r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%d\n",ans);
}    
View Code

 

 

 

 

 

BZOJ - 3631  squirrels home (LCA + tree differential)

Title effect:
Given an n-$ $ undirected tree nodes, a person present in accordance with a given sequence of length n-running $ $ requiring him to reach every point, that point should be placed a candy necessary to add tree because the last node sequence is the kitchen, so the last node does not need to +1, the number of candy output of each node should be placed
problem-solving analysis: the
meaning of the questions looked a long time did not understand, in fact, each sequence from $ a_ { i-1} $ $ come a_i $, where each $ 1 + $ node, then the challenge value for each node. Split bare tree chain problem, of course, is a tree difference and LCA bare title, so this question written on a tree difference, is relatively simple. Note that: $ a_2, a_3 \ dots a_ {n-1} $ must $ $ -1, as calculated repeated once, and the $ $ A_N also -1 because when it is not the end of its sequence is placed as candy.

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
template<typename T>inline void rd(T&x){
    x=0;int f=1;char ch=getchar();
    while(ch<'0' ||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); }
    while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
    x*=f;
}
#define RP(i,s,t) for(int i=s;i<=t;i++)
const int N = 3e5+5;
typedef long long ll;
int n,a[N];
vector<int>G[N];

int f[N][30],dep[N];
ll sum[N];

void dfs(int u,int fa){       
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa)continue;
        if(!dep[v]){
            dep[v]=dep[u]+1;
            f[v][0]=u;
            dfs(v,u);
        }
    }
}
void ST(){        
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            f[i][j]=f[f[i][j-1]][j-1];
}
int LCA(int a,int b){          
    if(dep[b]<dep[a])swap(a,b); 
    int d=dep[b]-dep[a];
    for(int i=0;(d>>i)!=0;i++)
        if((d>>i)&1)b=f[b][i];   
    if(a==b)return b;  
    for(int i=20;i>=0;i--) 
        if(f[b][i]!=f[a][i])   
            b=f[b][i],a=f[a][i];  
    return f[b][0];   
}
void sumdfs(int u,int pre){
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==pre)continue;
        sumdfs(v,u);
        sum[u]+=sum[v];
    }
}
int main(){
    rd(n);
    RP(i,1,n)rd(a[i]);
    RP(i,2,n){
        int u,v;rd(u);rd(v);
        G[u].pb(v);G[v].pb(u);
    }
    dep[1]=1;
    dfs(1,-1);
    ST();
    RP(i,2,n){
        int u=a[i-1],v=a[i];
        int lca=LCA(u,v);
        sum[u]++;sum[v]++;sum[lca]--;sum[f[lca][0]]--;            //树上差分部分        
    }
    sumdfs(1,-1);
    RP(i,2,n)sum[a[i]]--;
    RP(i,1,n)printf("%lld\n",sum[i]);
}
View Code

 

Guess you like

Origin www.cnblogs.com/00isok/p/11346267.html