hdu 3966 树链剖分模版

来源:互联网 发布:申请网络空间 编辑:程序博客网 时间:2024/05/16 12:12

 

 

#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  ;}

0 0
原创粉丝点击