按层建线段树,或者说是bfs序。
然后修改的一定是不超过5层里面的连续的段,可以在线段树上直接修改。
对于环+树,把环抠出来之后按树的方法做。
代码丑
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char &x){
for (x=nc();!(x>='A' && x<='Z');x=nc());
}
const int N=100005;
namespace BIT{
int maxn; ll c1[N],c2[N];
inline void init(int n){
maxn=n; for (int i=1;i<=n;i++) c1[i]=c2[i]=0;
}
inline void add(int x,int d){
for (int i=x;i<=maxn;i+=i&-i)
c1[i]+=d,c2[i]+=x*d;
}
inline void add(int l,int r,int d){
if (l>r) return;
add(l,d); add(r+1,-d);
}
inline ll sum(int x){
ll ret1=0,ret2=0;
for (int i=x;i;i-=i&-i)
ret1+=c1[i],ret2+=c2[i];
return ret1*(x+1)-ret2;
}
inline ll sum(int l,int r){
if (l>r) return 0;
return sum(r)-sum(l-1);
}
}
struct edge{
int u,v,next;
}G[N<<1];
int head[N],inum;
inline void edd(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int inp[N],pth[N];
int fat[N],depth[N];
#define V G[p].v
inline void dfs(int u,int fa){
fat[u]=fa; depth[u]=depth[fa]+1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
if (!depth[V])
dfs(V,u);
else if (depth[V]<depth[u]){
int t=u;
while (t!=V)
pth[++*pth]=t,inp[t]=*pth,t=fat[t];
pth[++*pth]=t,inp[t]=*pth;
}
}
int n;
int rt[N];
int clk,pre[N],lp[N],rp[N],lp2[N],rp2[N];
int l,r,Q[N];
inline void bfs(int S){
l=r=0; Q[++r]=S; fat[S]=0; depth[S]=0; pre[S]=++clk;
while (l<r){
int u=Q[++l];
for (int p=head[u];p;p=G[p].next)
if (V!=fat[u] && !inp[V])
Q[++r]=V,pre[V]=++clk,fat[V]=u,depth[V]=depth[u]+1;
}
for (int i=r;i;i--){
int u=Q[i],fa=fat[u];
rt[u]=S;
if (!fa) continue;
lp[fa]=min(lp[fa],pre[u]);
rp[fa]=max(rp[fa],pre[u]);
lp2[fa]=min(lp2[fa],lp[u]);
rp2[fa]=max(rp2[fa],rp[u]);
}
}
inline int Pre(int x){ return pth[inp[x]==1?*pth:inp[x]-1]; }
inline int Nxt(int x){ return pth[inp[x]==*pth?1:inp[x]+1]; }
int vst[N];
inline void Add(int x,int d,int k){
int fa=fat[x];
using namespace BIT;
if (d==0){
add(pre[x],pre[x],k);
}else if (d==1){
add(lp[x],rp[x],k);
add(pre[x],pre[x],k);
if (depth[x]>0){
add(pre[fa],pre[fa],k);
}else{
add(pre[Pre(x)],pre[Pre(x)],k);
add(pre[Nxt(x)],pre[Nxt(x)],k);
}
}else{
add(lp2[x],rp2[x],k);
add(lp[x],rp[x],k);
if (depth[x]>1){
add(lp[fa],rp[fa],k);
add(pre[fa],pre[fa],k);
add(pre[fat[fa]],pre[fat[fa]],k);
}else if (depth[x]==1){
add(lp[fa],rp[fa],k);
add(pre[fa],pre[fa],k);
add(pre[Pre(fa)],pre[Pre(fa)],k);
add(pre[Nxt(fa)],pre[Nxt(fa)],k);
}else if (depth[x]==0){
add(pre[x],pre[x],k);
add(pre[Pre(x)],pre[Pre(x)],k);
add(lp[Pre(x)],rp[Pre(x)],k);
add(pre[Nxt(x)],pre[Nxt(x)],k);
add(lp[Nxt(x)],rp[Nxt(x)],k);
vst[x]=vst[Pre(x)]=vst[Nxt(x)]=1;
int t1,t2;
if (!vst[t1=Pre(Pre(x))])
add(pre[t1],pre[t1],k),vst[t1]=1;
if (!vst[t2=Nxt(Nxt(x))])
add(pre[t2],pre[t2],k),vst[t2]=1;
vst[x]=vst[Pre(x)]=vst[Nxt(x)]=vst[t1]=vst[t2]=0;
}
}
}
inline ll Sum(int x,int d){
ll ret=0;
int fa=fat[x];
using namespace BIT;
if (d==0){
ret+=sum(pre[x],pre[x]);
}else if (d==1){
ret+=sum(lp[x],rp[x]);
ret+=sum(pre[x],pre[x]);
if (depth[x]>0){
ret+=sum(pre[fa],pre[fa]);
}else{
ret+=sum(pre[Pre(x)],pre[Pre(x)]);
ret+=sum(pre[Nxt(x)],pre[Nxt(x)]);
}
}else{
ret+=sum(lp2[x],rp2[x]);
ret+=sum(lp[x],rp[x]);
if (depth[x]>1){
ret+=sum(lp[fa],rp[fa]);
ret+=sum(pre[fa],pre[fa]);
ret+=sum(pre[fat[fa]],pre[fat[fa]]);
}else if (depth[x]==1){
ret+=sum(lp[fa],rp[fa]);
ret+=sum(pre[fa],pre[fa]);
ret+=sum(pre[Pre(fa)],pre[Pre(fa)]);
ret+=sum(pre[Nxt(fa)],pre[Nxt(fa)]);
}else if (depth[x]==0){
ret+=sum(pre[x],pre[x]);
ret+=sum(pre[Pre(x)],pre[Pre(x)]);
ret+=sum(lp[Pre(x)],rp[Pre(x)]);
ret+=sum(pre[Nxt(x)],pre[Nxt(x)]);
ret+=sum(lp[Nxt(x)],rp[Nxt(x)]);
vst[x]=vst[Pre(x)]=vst[Nxt(x)]=1;
int t1,t2;
if (!vst[t1=Pre(Pre(x))])
ret+=sum(pre[t1],pre[t1]),vst[t1]=1;
if (!vst[t2=Nxt(Nxt(x))])
ret+=sum(pre[t2],pre[t2]),vst[t2]=1;
vst[x]=vst[Pre(x)]=vst[Nxt(x)]=vst[t1]=vst[t2]=0;
}
}
return ret;
}
int main(){
int T,Q,iu,iv,k; char order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(T);
while (T--){
read(n);
for (int i=1;i<=n;i++) head[i]=0; inum=0;
for (int i=1;i<=n;i++) read(iu),read(iv),edd(iu,iv,++inum),edd(iv,iu,++inum);
for (int i=1;i<=n;i++) depth[i]=0,inp[i]=0;
*pth=0; dfs(1,0);
for (int i=1;i<=n;i++) lp[i]=lp2[i]=n+1,rp[i]=rp2[i]=0;
clk=0;
for (int i=1;i<=n;i++) fat[i]=depth[i]=0;
for (int i=1;i<=*pth;i++) bfs(pth[i]);
BIT::init(n);
read(Q);
while (Q--){
read(order); read(iu); read(iv);
if (order=='M') read(k),Add(iu,iv,k);
else printf("%I64d\n",Sum(iu,iv));
}
}
return 0;
}