hdu_3966_Aragorn's Story(树链剖分裸题)

时间:2024-10-16 18:05:39

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

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

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

 #include<cstdio>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define F(i,a,b) for(int i=a;i<=b;++i) const int N=;char op[];
int n,m,p,tp,x,y,k,a[N],tree[N],nxt[*N],g[N],v[*N],ed,hs[N],fa[N],top[N],dep[N],siz[N],idx,tid[N]; inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
//树状树组部分
inline void update(int x,int k){while(x<=n)tree[x]+=k,x+=x&-x;}
inline int sum(int x){int ans=;for(;x>;x-=x&-x)ans+=tree[x];return ans;}
//树链部分
void dfs1(int u,int pre){
fa[u]=pre,siz[u]=,dep[u]=dep[pre]+,hs[u]=;
for(int i=g[u];~i;i=nxt[i]){
int vv=v[i];
if(vv!=pre){
dfs1(vv,u);
if(siz[vv]>siz[hs[u]])hs[u]=vv;
siz[u]+=siz[vv];
}
}
} void dfs2(int u,int tp){
tid[u]=++idx,top[u]=tp;
if(hs[u])dfs2(hs[u],tp);
for(int i=g[u];~i;i=nxt[i]){
int vv=v[i];
if(vv!=fa[u]&&vv!=hs[u])dfs2(vv,vv);
}
} void up(int x,int y,int k){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]>=dep[fy])update(tid[fx],k),update(tid[x]+,-k),x=fa[fx],fx=top[x];
else update(tid[fy],k),update(tid[y]+,-k),y=fa[fy],fy=top[y];
}
if(dep[x]>dep[y])x=x^y,y=x^y,x=x^y;
update(tid[x],k),update(tid[y]+,-k);
} int main(){
while(~scanf("%d%d%d",&n,&m,&p)){
F(i,,n)scanf("%d",a+i);
F(i,,N-)g[i]=-,tree[i]=;ed=;
F(i,,m)scanf("%d%d",&x,&y),adg(x,y),adg(y,x);
dfs1(,),idx=,dfs2(,);
F(i,,p){
scanf("%s",op);
if(op[]=='I')scanf("%d%d%d",&x,&y,&k),up(x,y,k);
else if(op[]=='D')scanf("%d%d%d",&x,&y,&k),up(x,y,-k);
else scanf("%d",&k),printf("%d\n",sum(tid[k])+a[k]);
}
}
return ;
}