思路:
用线段树维护bfs序,因为同一层的儿子的bfs序连续
很久没有写过分类讨论了
细节错误很多:
1. k == 2时要判在不在环上,环够不够长,fa[x]在不在环上
2. bfs序只保证所有儿子在连续区间,而层与层之间是不连续的。开始竟然天真的以为是连续的
调了 1h多 还写了 30多min 代码能力要加强!
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define repd(i,a,b) for(int i=a;i>=b;--i)
#define rvc(i,S) for(int i=0;i<(int)S.size();++i)
#define fore(i,x) for(int i = head[x] ; i ; i = e[i].next)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lowbit(x) (x&(-x))
using namespace std;
#define maxn 100020
typedef long long ll;
int n,T,m;
struct node{
int next,to;
}e[maxn * 2];
int head[maxn],cnt,tag[maxn],a[maxn],tot,pre[maxn],post[maxn],fa[maxn];
int l[maxn],r[maxn],dfn[maxn],q[maxn],hh,tt,times,l2[maxn],r2[maxn];
int st[maxn],tops,vis[maxn],bl;
ll sum[maxn << 2],add[maxn << 2];
char ch[20];
void clear(){
rep(i,1,n){
head[i] = tag[i] = fa[i] = post[i] = pre[i] = dfn[i] = vis[i] = 0;
}
rep(i,1,n << 2){
sum[i] = add[i] = 0;
}
times = tops = bl = tt = hh = cnt = tot = 0;
}
inline void adde(int x,int y){
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
void dfs(int x,int fa){
if ( vis[x] ){
while ( st[tops] != x ){
a[++tot] = st[tops--], tag[a[tot]] = 1;
}
a[++tot] = x , tag[x] = 1;
bl = 1;
return;
}
vis[x] = 1 , st[++tops] = x;
fore(i,x){
if ( e[i].to == fa ) continue;
dfs(e[i].to,x);
if ( bl ) return;
}
tops--;
}
void bfs(int x){
tt = hh = 0;
q[tt++] = x;
dfn[x] = ++times;
while ( hh < tt ){
int x = q[hh++];
fore(i,x){
if ( !tag[e[i].to] && !dfn[e[i].to] ){
dfn[e[i].to] = ++times;
fa[e[i].to] = x;
q[tt++] = e[i].to;
}
}
}
repd(i,tt - 1,0){
int x = q[i];
l[x] = l2[x] = n , r[x] = r2[x] = 0;
fore(j,x){
if ( !tag[e[j].to] && fa[e[j].to] == x ){
r[x] = max(r[x],dfn[e[j].to]);
r2[x] = max(r2[x],r[e[j].to]);
l[x] = min(l[x],dfn[e[j].to]);
l2[x] = min(l2[x],l[e[j].to]);
}
}
}
}
void init(){
//find_circle
dfs(1,0);
a[0] = a[tot] , a[tot + 1] = a[1];
rep(i,1,tot){
int x = a[i];
pre[x] = a[i - 1];
post[x] = a[i + 1];
bfs(x);
if ( l[x] > r[x] ) l[x] = dfn[x] + 1,r[x] = dfn[x];
}
}
inline void add_(int x,int l,int r,ll d){
add[x] += d;
sum[x] += (ll)d * (r - l + 1);
}
inline void pushdown(int x,int l,int r,int mid){
if ( add[x] != 0 ){
add_(x << 1,l,mid,add[x]);
add_((x << 1) | 1,mid + 1,r,add[x]);
add[x] = 0;
}
}
inline void update(int x){
sum[x] = sum[x << 1] + sum[(x << 1) | 1];
}
void modify(int x,int l,int r,int L,int R,int d){
if ( L > R ) return;
if ( L <= l && R >= r ){
add_(x,l,r,d);
return;
}
int mid = (l + r) >> 1;
pushdown(x,l,r,mid);
if ( L <= mid ) modify(x << 1,l,mid,L,R,d);
if ( R > mid ) modify((x << 1) | 1,mid + 1,r,L,R,d);
update(x);
}
ll query(int x,int l,int r,int L,int R){
if ( L > R ) return 0;
if ( L <= l && R >= r ) return sum[x];
int mid = (l + r) >> 1; ll res = 0;
pushdown(x,l,r,mid);
if ( L <= mid ) res = query(x << 1,l,mid,L,R);
if ( R > mid ) res += query((x << 1) | 1,mid + 1,r,L,R);
return res;
}
void modify(int x,int k,int d){
if ( tag[x] ){
if ( k == 2 ){
//环上的点和儿子的bfs序连续,但其他点不一定连续
//bfs序只满足同一层的所有儿子连续的性质
modify(1,1,n,l[pre[x]] - 1,r[pre[x]],d);
//modify(1,1,n,dfn[pre[x]],dfn[pre[x]],d);
modify(1,1,n,l[post[x]] - 1,r[post[x]],d);
//modify(1,1,n,dfn[post[x]],dfn[post[x]],d);
modify(1,1,n,l2[x],r2[x],d);
modify(1,1,n,l[x] - 1,r[x],d);
if ( tot == 3 );
else if ( tot == 4 ) modify(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]],d);
else{
modify(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]],d);
modify(1,1,n,dfn[post[post[x]]],dfn[post[post[x]]],d);
}
}
else if ( k == 1 ){
modify(1,1,n,dfn[pre[x]],dfn[pre[x]],d);
modify(1,1,n,dfn[post[x]],dfn[post[x]],d);
modify(1,1,n,l[x] - 1,r[x],d);
//modify(1,1,n,dfn[x],dfn[x],d);
}
else modify(1,1,n,dfn[x],dfn[x],d);
}
else{
int p = fa[x];
if ( k == 2 ){
modify(1,1,n,l2[x],r2[x],d);
modify(1,1,n,l[x],r[x],d);
modify(1,1,n,dfn[p],dfn[p],d);
modify(1,1,n,l[p],r[p],d);
if ( tag[p] ){
modify(1,1,n,dfn[pre[p]],dfn[pre[p]],d);
modify(1,1,n,dfn[post[p]],dfn[post[p]],d);
}
else modify(1,1,n,dfn[fa[p]],dfn[fa[p]],d);
}
else if ( k == 1 ){
modify(1,1,n,l[x],r[x],d);
modify(1,1,n,dfn[x],dfn[x],d);
modify(1,1,n,dfn[p],dfn[p],d);
}
else modify(1,1,n,dfn[x],dfn[x],d);
}
}
ll query(int x,int k){
ll res = 0;
if ( tag[x] ){
if ( k == 2 ){
res += query(1,1,n,l2[x],r2[x]);
res += query(1,1,n,l[x] - 1,r[x]);
res += query(1,1,n,l[pre[x]] - 1,r[pre[x]]);
res += query(1,1,n,l[post[x]] - 1,r[post[x]]);
if ( tot == 3 );
else if ( tot == 4 ) res += query(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]]);
else{
res += query(1,1,n,dfn[pre[pre[x]]],dfn[pre[pre[x]]]);
res += query(1,1,n,dfn[post[post[x]]],dfn[post[post[x]]]);
}
}
else if ( k == 1 ){
res += query(1,1,n,l[x] - 1,r[x]);
res += query(1,1,n,dfn[pre[x]],dfn[pre[x]]);
res += query(1,1,n,dfn[post[x]],dfn[post[x]]);
}
else res += query(1,1,n,dfn[x],dfn[x]);
}
else{
int p = fa[x];
if ( k == 2 ){
res += query(1,1,n,l2[x],r2[x]);
res += query(1,1,n,l[x],r[x]);
res += query(1,1,n,dfn[p],dfn[p]);
res += query(1,1,n,l[p],r[p]);
if ( tag[p] ){
res += query(1,1,n,dfn[pre[p]],dfn[pre[p]]);
res += query(1,1,n,dfn[post[p]],dfn[post[p]]);
}
else res += query(1,1,n,dfn[fa[p]],dfn[fa[p]]);
}
else if ( k == 1 ){
res += query(1,1,n,l[x],r[x]);
res += query(1,1,n,dfn[x],dfn[x]);
res += query(1,1,n,dfn[p],dfn[p]);
}
else res += query(1,1,n,dfn[x],dfn[x]);
}
return res;
}
int main(){
freopen("input.txt","r",stdin);
scanf("%d",&T);
while ( T-- ){
scanf("%d",&n);
clear();
rep(i,1,n){
int x,y;
scanf("%d %d",&x,&y);
adde(x,y) , adde(y,x);
}
init();
/* for (int i = 1 ; i <= n ; i++){
cout<<dfn[i]<<" "<<l[i]<<" "<<r[i]<<" "<<l2[i]<<" "<<r2[i]<<endl;
}*/
scanf("%d",&m);
while ( m-- ){
scanf("%s",ch);
int x,k,d;
if ( ch[0] == 'M' ){
scanf("%d %d %d",&x,&k,&d);
modify(x,k,d);
}
else{
scanf("%d %d",&x,&k);
printf("%lld\n",query(x,k));
}
}
}
}