CF191C 树链剖分


点击打开链接

给出K个路径, 统计经过每条边的次数。

边的标记 与 下面的u一致


const  int  maxn = 100008 ;

int  n ;
int  siz[maxn] , top[maxn] , son[maxn] ;
int  dep[maxn] , tid[maxn] , fa[maxn] , rank[maxn]  ;
int  head[maxn] , to[maxn*2] , next[maxn*2] , edge ;
int  tim ;

void  init(){
      memset(head , -1 , sizeof(head)) ;
      memset(son , -1 , sizeof(son))  ;
      tim = edge = 0 ;
}

void  addedge(int u , int v){
      to[edge] = v , next[edge] = head[u] , head[u] = edge++ ;
      to[edge] = u , next[edge] = head[v] , head[v] = edge++ ;
}

void  dfs1(int u , int father , int d){
      dep[u] = d ;
      fa[u]  = father ;
      siz[u] = 1 ;
      for(int i = head[u] ; i != -1 ; i = next[i]){
            int v = to[i] ;
            if(v != father){
                 dfs1(v , u , d+1) ;
                 siz[u] += siz[v] ;
                 if(son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v ;
            }
      }
}

void  dfs2(int u , int tp){
      top[u] = tp ;
      tid[u] = ++tim ;
      rank[tid[u]] = u ;
      if(son[u] == -1) return  ;
      dfs2(son[u] , tp) ;
      for(int i = head[u] ; i != -1 ; i = next[i]){
           int v = to[i] ;
           if(v != son[u] && v != fa[u])  dfs2(v , v) ;
      }
}

int  c[maxn] ;

int  lowbit(int x){
     return x & (-x) ;
}

int  in(int i , int d){
     for( ; i <= n ; i += lowbit(i)) c[i] += d ;
}

int  gsum(int i){
     int t = 0 ;
     for( ; i >= 1 ; i -= lowbit(i)) t += c[i] ;
     return t  ;
}

struct  Line{
      int  u ,  v , id ;
}li[maxn]  ;

void  change(int x , int y){
      while(top[x] != top[y]){
           if(dep[top[x]] < dep[top[y]]) std::swap(x , y) ;
           in(tid[top[x]] , 1) ;
           in(tid[x] + 1 , -1) ;
           x = fa[top[x]] ;
      }
      if(x == y) return  ;
      if(dep[x] > dep[y]) std::swap(x , y) ;
      in(tid[x]+1 , 1) ;
      in(tid[y]+1 , -1) ;
}

int   main(){
      int i , j , u , v  , k  ;
      while(scanf("%d" , &n) != EOF){

           init() ;
           for(i = 1 ; i < n ; i++){
                scanf("%d%d" , &li[i].u , &li[i].v) ;
                li[i].id = i ;
                addedge(li[i].u , li[i].v) ;
           }

           dfs1(1 , 0 , 0) ;
           dfs2(1 , 1) ;

           for(i = 1 ; i < n ; i++){
                if(tid[li[i].u] < tid[li[i].v])
                    std::swap(li[i].u , li[i].v) ;
           }

           memset(c , 0 , sizeof(c)) ;
           scanf("%d" , &k) ;
           for(i = 1 ; i <= k ; i++){
                scanf("%d%d" , &u , &v) ;
                change(u , v) ;
           }
           for(i = 1 ; i < n ; i++)  printf("%d " , gsum(tid[li[i].u]))  ;
           puts("") ;

      }
      return  0 ;
}


你可能感兴趣的:(CF191C 树链剖分)