zoukankan      html  css  js  c++  java
  • hdu_3966_Aragorn's Story(树链剖分裸题)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3966

    题意:给你一棵树,然后给定点之间的路径权值修改,最后单点查询

    题解:树链剖分裸题,这里我用树状数组维护


     1 #include<cstdio>
     2 #pragma comment(linker, "/STACK:1024000000,1024000000")
     3 #define F(i,a,b) for(int i=a;i<=b;++i)
     4 
     5 const int N=50010;char op[2];
     6 int n,m,p,tp,x,y,k,a[N],tree[N],nxt[2*N],g[N],v[2*N],ed,hs[N],fa[N],top[N],dep[N],siz[N],idx,tid[N];
     7 
     8 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
     9 //树状树组部分
    10 inline void update(int x,int k){while(x<=n)tree[x]+=k,x+=x&-x;}
    11 inline int sum(int x){int ans=0;for(;x>0;x-=x&-x)ans+=tree[x];return ans;}
    12 //树链部分
    13 void dfs1(int u,int pre){
    14     fa[u]=pre,siz[u]=1,dep[u]=dep[pre]+1,hs[u]=0;
    15     for(int i=g[u];~i;i=nxt[i]){
    16         int vv=v[i];
    17         if(vv!=pre){
    18             dfs1(vv,u);
    19             if(siz[vv]>siz[hs[u]])hs[u]=vv;
    20             siz[u]+=siz[vv];
    21         }
    22     }
    23 }
    24 
    25 void dfs2(int u,int tp){
    26     tid[u]=++idx,top[u]=tp;
    27     if(hs[u])dfs2(hs[u],tp);
    28     for(int i=g[u];~i;i=nxt[i]){
    29         int vv=v[i];
    30         if(vv!=fa[u]&&vv!=hs[u])dfs2(vv,vv);
    31     }
    32 }
    33 
    34 void up(int x,int y,int k){
    35     int fx=top[x],fy=top[y];
    36     while(fx!=fy){
    37         if(dep[fx]>=dep[fy])update(tid[fx],k),update(tid[x]+1,-k),x=fa[fx],fx=top[x];
    38         else update(tid[fy],k),update(tid[y]+1,-k),y=fa[fy],fy=top[y];
    39     }
    40     if(dep[x]>dep[y])x=x^y,y=x^y,x=x^y;
    41     update(tid[x],k),update(tid[y]+1,-k);
    42 }
    43 
    44 int main(){
    45     while(~scanf("%d%d%d",&n,&m,&p)){
    46         F(i,1,n)scanf("%d",a+i);
    47         F(i,0,N-1)g[i]=-1,tree[i]=0;ed=0;
    48         F(i,1,m)scanf("%d%d",&x,&y),adg(x,y),adg(y,x);
    49         dfs1(1,0),idx=0,dfs2(1,1);
    50         F(i,1,p){
    51             scanf("%s",op);
    52             if(op[0]=='I')scanf("%d%d%d",&x,&y,&k),up(x,y,k);
    53             else if(op[0]=='D')scanf("%d%d%d",&x,&y,&k),up(x,y,-k);
    54             else scanf("%d",&k),printf("%d
    ",sum(tid[k])+a[k]);
    55         }
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    nj07---npm
    nj06---包
    nj05---模块
    nj04---事件回调函数
    nj03---阻塞和线程
    nodejs02---demo
    nodejs简介
    【转贴】内存系列一:快速读懂内存条标签
    【转贴】4个你未必知道的内存小知识
    Linux上面mount 域控的目录 超时 然后提示 error的解决办法
  • 原文地址:https://www.cnblogs.com/bin-gege/p/5696117.html
Copyright © 2011-2022 走看看