点击打开链接
题意:中文
思路:如果没有多次询问的话,就可以直接用简单的DFS与LCA就可以完成,然而却多加了个变换根的操作,那么怎么办,与刚刚写的那道点这里类似,都是可以变根的,建议先写那道再写这个,思想都是一样的,那么这道题我们也是以1为根先进行LCA与DFS,然后每次的根与询问就是那道题的换根的部分,这不太好说只能自己理解了
#include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=10010; bool vis[maxn]; int L[maxn*2],E[maxn*2],H[maxn],dis[maxn],dp[2*maxn][20],num[maxn],sum[maxn],head[maxn],kkk,pre[maxn]; struct node{ int to,next; }EE[maxn*10]; void add_edge(int u,int v){ EE[kkk].to=v;EE[kkk].next=head[u];head[u]=kkk++; } int k,n; void dfs(int t,int deep){ k++;E[k]=t;L[k]=deep;H[t]=k; for(int i=head[t];i!=-1;i=EE[i].next){ int tt=EE[i].to; if(!vis[tt]){ vis[tt]=1;pre[tt]=t; dfs(tt,deep+1); k++;E[k]=t;L[k]=deep; } } } void RMQ_init(){ for(int i=1;i<=2*n-1;i++) dp[i][0]=i; for(int i=1;(1<<i)<=2*n-1;i++){ for(int j=1;j+(1<<i)-1<=2*n-1;j++){ if(L[dp[j][i-1]]<L[dp[j+(1<<(i-1))][i-1]]) dp[j][i]=dp[j][i-1]; else dp[j][i]=dp[j+(1<<(i-1))][i-1]; } } } int RMQ(int le,int ri){ le=H[le];ri=H[ri]; if(le>ri) swap(le,ri); int kk=0; while((1<<(kk+1))<=ri-le+1) kk++; if(L[dp[le][kk]]<L[dp[ri-(1<<kk)+1][kk]]) return E[dp[le][kk]]; else return E[dp[ri-(1<<kk)+1][kk]]; } void DFS(int x,int fa){ for(int i=head[x];i!=-1;i=EE[i].next){ int t=EE[i].to; if(t==fa) continue; DFS(t,x); sum[x]+=sum[t]; } } int main(){ int q,u,v,T,cas=1; char ch[10]; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<=n;i++) vis[i]=0; for(int i=0;i<=n;i++) head[i]=-1; for(int i=0;i<n-1;i++){ scanf("%d%d",&u,&v); add_edge(u,v);add_edge(v,u); } for(int i=1;i<=n;i++) scanf("%d",&num[i]),sum[i]=num[i]; kkk=0;k=0;vis[1]=1;dfs(1,1);RMQ_init(); DFS(1,1); scanf("%d",&q); int root=1; printf("Case #%d:\n",cas++); while(q--){ scanf("%s",ch); if(ch[0]=='R'){ scanf("%d",&u); root=u; }else if(ch[0]=='C'){ scanf("%d%d",&u,&v); int ttt=u; while(u!=1){ sum[u]+=(v-num[ttt]); u=pre[u]; } sum[1]+=(v-num[ttt]); num[ttt]=v; }else if(ch[0]=='Q'){ scanf("%d",&u); int en=RMQ(root,u); if(en!=u) printf("%d\n",sum[u]); else{ if(root==u){ printf("%d\n",sum[1]);continue; } int a=L[H[root]],b=L[H[u]]; int len=a-b-1; if(len==0) printf("%d\n",sum[1]-sum[root]); else{ int ans=root; while(len--) ans=pre[ans]; printf("%d\n",sum[1]-sum[ans]); } } } } } return 0; }