题意:
n个点n条边的连通图,边长度都为1,没有重边自环,两种操作:
1.把与x距离小于等于k的所有点的权值增加d (k<=2)
2.问离x距离小于等于k的所有点的权值和 (k<=2)
思路:
首先这是个环套树,找到环后从环上的每个点开始bfs,处理出每个点向子树走k步的bfs序区间,一层层维护就好了。
分类讨论比较麻烦。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100005;
ll lazy[4*N],sum[4*N];
int n;
void init()
{
memset(lazy,0,sizeof(lazy));
memset(sum,0,sizeof(sum));
}
void up(int x)
{
sum[x]=sum[x*2]+sum[x*2+1];
}
void down(int x,int l,int r)
{
if (lazy[x])
{
int mid=(l+r)/2;
sum[x*2]+=(mid-l+1)*lazy[x];
sum[x*2+1]+=(r-mid)*lazy[x];
lazy[x*2]+=lazy[x];
lazy[x*2+1]+=lazy[x];
lazy[x]=0;
}
}
void add(int i,int l,int r,int x,int y,int w)
{
if (x<=l&&r<=y)
{
sum[i]+=w*(r-l+1);
lazy[i]+=w;
return;
}
down(i,l,r);
int mid=(l+r)/2;
if (x<=mid) add(i*2,l,mid,x,y,w);
if (y>mid) add(i*2+1,mid+1,r,x,y,w);
up(i);
}
ll get(int i,int l,int r,int x,int y)
{
if (x<=l&&r<=y) return sum[i];
down(i,l,r);
int mid=(l+r)/2;
ll ret=0;
if (x<=mid) ret+=get(i*2,l,mid,x,y);
if (y>mid) ret+=get(i*2+1,mid+1,r,x,y);
return ret;
}
void ad(int l,int r,int w)
{
if (l>r) return;
add(1,1,n,l,r,w);
}
ll gt(int l,int r)
{
if (l>r) return 0;
return get(1,1,n,l,r);
}
bool vis[N],on[N];
int l[N],r[N];
vector<int>link[N];
int dfs1(int u,int fa)
{
vis[u]=1;
for (int i=0;i<link[u].size();i++)
{
int v=link[u][i];
if (v==fa) continue;
l[v]=u;
if (vis[v]) return v;
int tmp=dfs1(v,u);
if (tmp) return tmp;
}
return 0;
}
int tot;
int q[N],bl[N][3],br[N][3],fa[N];
void bfs(int u)
{
vis[u]=1;
q[++tot]=u;
bl[u][0]=tot; bl[u][1]=bl[u][2]=N;
br[u][0]=tot; br[u][1]=br[u][2]=0;
int head=tot;
while(head<=tot)
{
int u=q[head]; head++;
for (int i=0;i<link[u].size();i++)
{
int v=link[u][i];
if (vis[v]||on[v]) continue;
q[++tot]=v;
bl[v][0]=tot; bl[v][1]=bl[v][2]=N;
br[v][0]=tot; br[v][1]=br[v][2]=0;
fa[v]=u;
vis[v]=1;
}
}
}
void look(int n)
{
for (int i=1;i<=n;i++)
{
printf("%d %lld\n",i,get(1,1,n,bl[i][0],br[i][0]));
}
}
char s[10];
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x,y; scanf("%d%d",&x,&y);
link[x].push_back(y);
link[y].push_back(x);
}
for (int i=1;i<=n;i++) vis[i]=0,on[i]=0;
int root=dfs1(1,1);
r[l[root]]=root; on[root]=1;
for (int i=l[root];i!=root;i=l[i]) r[l[i]]=i,on[i]=1;
tot=0;
for (int i=1;i<=n;i++) vis[i]=0;
bfs(root);
for (int i=l[root];i!=root;i=l[i]) bfs(i);
for (int k=1;k<=2;k++)
for (int i=tot;i>=1;i--)
{
int v=q[i];
if (on[v]) continue;
int u=fa[v];
bl[u][k]=min(bl[u][k],bl[v][k-1]);
br[u][k]=max(br[u][k],br[v][k-1]);
}
init();
int m; scanf("%d",&m);
while(m--)
{
//look(n);
scanf("%s",s);
if (s[0]=='M')
{
int u,k,w; scanf("%d%d%d",&u,&k,&w);
if (k==0) ad(bl[u][0],br[u][0],w);
if (k==1)
{
ad(bl[u][0],br[u][0],w);
ad(bl[u][1],br[u][1],w);//
if (on[u])
{
int lv=l[u],rv=r[u];
ad(bl[lv][0],br[lv][0],w);
ad(bl[rv][0],br[rv][0],w);
}
else
{
int v=fa[u];
ad(bl[v][0],br[v][0],w);
}
}
if (k==2)
{
ad(bl[u][0],br[u][0],w);
ad(bl[u][1],br[u][1],w);
ad(bl[u][2],br[u][2],w);
if (on[u])
{
int lv=l[u];
ad(bl[lv][0],br[lv][0],w);
ad(bl[lv][1],br[lv][1],w);
int rv=r[u];
ad(bl[rv][0],br[rv][0],w);
ad(bl[rv][1],br[rv][1],w);
lv=l[lv];
if (lv!=rv)
ad(bl[lv][0],br[lv][0],w);
else lv=r[lv];
rv=r[rv];
if (rv!=lv)
ad(bl[rv][0],br[rv][0],w);
}
else
{
int v=fa[u];
ad(bl[v][0],br[v][0],w);
ad(bl[v][1],br[v][1],w);
ad(bl[u][0],br[u][0],-w);
if (on[v])
{
int lv=l[v],rv=r[v];
ad(bl[lv][0],br[lv][0],w);
ad(bl[rv][0],br[rv][0],w);
}
else
{
v=fa[v];
ad(bl[v][0],br[v][0],w);
}
}
}
}
if (s[0]=='Q')
{
int u,k,w; scanf("%d%d",&u,&k);
ll ret=0;
if (k==0) ret+=gt(bl[u][0],br[u][0]);
if (k==1)
{
ret+=gt(bl[u][0],br[u][0]);
ret+=gt(bl[u][1],br[u][1]);
if (on[u])
{
int lv=l[u],rv=r[u];
ret+=gt(bl[lv][0],br[lv][0]);
ret+=gt(bl[rv][0],br[rv][0]);
}
else
{
int v=fa[u];
ret+=gt(bl[v][0],br[v][0]);
}
}
if (k==2)
{
ret+=gt(bl[u][0],br[u][0]);
ret+=gt(bl[u][1],br[u][1]);
ret+=gt(bl[u][2],br[u][2]);
if (on[u])
{
int lv=l[u];
ret+=gt(bl[lv][0],br[lv][0]);
ret+=gt(bl[lv][1],br[lv][1]);
int rv=r[u];
ret+=gt(bl[rv][0],br[rv][0]);
ret+=gt(bl[rv][1],br[rv][1]);
lv=l[lv];
if (lv!=rv)
ret+=gt(bl[lv][0],br[lv][0]);
else lv=r[lv];
rv=r[rv];
if (rv!=lv)
ret+=gt(bl[rv][0],br[rv][0]);
}
else
{
int v=fa[u];
ret+=gt(bl[v][0],br[v][0]);
ret+=gt(bl[v][1],br[v][1]);
ret-=gt(bl[u][0],br[u][0]);
if (on[v])
{
int lv=l[v],rv=r[v];
ret+=gt(bl[lv][0],br[lv][0]);
ret+=gt(bl[rv][0],br[rv][0]);
}
else
{
v=fa[v];
ret+=gt(bl[v][0],br[v][0]);
}
}
}
printf("%lld\n",ret);
}
}
for (int i=1;i<=n;i++) link[i].clear();
}
}
/*
1
8
1 2
2 3
3 4
1 4
2 5
3 6
5 7
5 8
12
MODIFY 8 1 5
MODIFY 8 2 2
QUERY 5 0
QUERY 5 1
QUERY 5 2
MODIFY 7 2 2
QUERY 7 2
MODIFY 3 1 5
MODIFY 2 2 2
QUERY 6 1
MODIFY 4 1 -2
QUERY 2 2
*/