hdu 3966 树链剖分模版

 

 

#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

typedef  long  long  LL ;

const   int   maxn = 50008 ;

int  n ;
int  siz[maxn] , top[maxn] , son[maxn] ;
int  dep[maxn] , tid[maxn] , rank[maxn] , fa[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) ;
      }
}

LL      sum[maxn<<2] , add[maxn<<2]  , a[maxn] ;

void    up(int t){
        sum[t] = sum[t<<1] + sum[t<<1|1] ;
}

void    down(int t , int l , int r){
        if(add[t]){
              int m = (l + r) >> 1 ;
              add[t<<1] += add[t] ;
              add[t<<1|1] += add[t] ;
              sum[t<<1] += add[t] * LL(m-l+1) ;
              sum[t<<1|1] += add[t] * LL(r - m) ;
              add[t] = 0 ;
        }
}

void    make(int l , int r , int t){
        add[t] = 0 ;
        if(l == r){
             sum[t] = a[rank[l]] ; return ;
        }
        int m = (l + r) >> 1 ;
        make(l , m , t<<1) ;
        make(m+1 , r , t<<1|1) ;
        up(t) ;
}

void    update(int L , int R , LL c , int l , int r , int t){
        if(L <= l && r <= R){
                add[t] += c ;
                sum[t] += c * LL(r - l + 1) ;
                return ;
        }
        down(t , l , r) ;
        int m = (l + r) >> 1 ;
        if(L <= m) update(L , R , c , l , m , t<<1) ;
        if(R > m)  update(L , R , c , m+1 , r , t<<1|1) ;
        up(t) ;
}

LL     ask(int l , int r , int t , int x){
       if(l == r)  return sum[t] ;
       down(t , l , r) ;
       int m = (l + r) >> 1 ;
       if(x <= m) return ask(l , m , t<<1 , x) ;
       else       return ask(m+1 , r , t<<1|1 , x) ;
}

void   change(int x , int y , LL c){
       while(top[x] != top[y]){
            if(dep[top[x]] < dep[top[y]]) swap(x , y) ;
            update(tid[top[x]] , tid[x] , c , 1 , n , 1) ;
            x = fa[top[x]] ;
       }
       if(dep[x] > dep[y]) swap(x , y) ;
       update(tid[x] , tid[y] , c , 1 , n , 1)  ;
}

int    main(){
       int  m ,  q , u , v ,  i , l , r ;
       LL c ;
       char s[2] ;

       while(scanf("%d%d%d" , &n , &m , &q) != EOF){
             for(i = 1 ; i <= n ; i++) scanf("%I64d" , &a[i]) ;

             init() ;
             while(m--){
                  scanf("%d%d" , &u , &v) ;
                  addedge(u , v) ;
             }
             dfs1(1 , 0 , 0) ;
             dfs2(1 , 1) ;

             make(1 , n , 1) ;
             while(q--){
                  scanf("%s" , s)  ;
                  if(s[0] == 'Q'){
                       scanf("%d" , &i) ;
                       printf("%I64d\n" , ask(1 , n , 1 , tid[i])) ;
                  }
                  else{
                       scanf("%d%d%I64d" , &l , &r , &c) ;
                       if(s[0] == 'D') c = -c ;
                       change(l , r , c) ;
                  }
             }
       }
       return  0  ;
}

你可能感兴趣的:(hdu 3966 树链剖分模版)