Tree Queries
Codeforces
水平有限,如有疏漏,墙裂欢迎提出
思路参考题解
算法标签:树链剖分
CF原题
简要题意: 给定一棵N个节点的树,有Q次操作
1:给定一个点v和一个权值d,等概率地选择一个点r,对每一个点u,若v在u到r的路径上,则u的权值加上d (权值一开始为0)
2: 查询v的权值期望,对
①
考虑对u点的贡献,若u在v子树内,则可以获得:
若u在v子树外,则可以获得:
如图:若v=6
口胡谁都会,我要看代码
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAX=150004;
const int mod=998244353;
struct edge{
int next,to;
}h[MAX<<1];
int head[MAX],cnt,cnt_dfsn;
int n,q,ans,inv;
inline void add(int x,int y){
h[++cnt]=edge{head[x],y};
head[x]=cnt;
h[++cnt]=edge{head[y],x};
head[y]=cnt;
}
int dfsn[MAX],size[MAX],son[MAX],fa[MAX],top[MAX],w[MAX];
int tree[MAX]; //差分
inline int lowbit(int x){
return x&(-x);
}
inline void ad(int x,int y){
y%=mod;
for(int i=x;i<=n;i+=lowbit(i))tree[i]=(tree[i]+y)%mod;
}
inline int sum(int x){
int ret=0;
for(int i=x;i;i-=lowbit(i))ret=(ret+tree[i])%mod;
return ret;
}
inline int quick(int x,int y){
int ret=1ll;
while(y){
if(y&1)ret=(ret*x)%mod;
y>>=1;
x=(x*x)%mod;
}
return ret;
}
void dfs1(int now,int father){
fa[now]=father;
size[now]=1;
for(int i=head[now];i;i=h[i].next){
int aim=h[i].to;
if(aim!=father){
dfs1(aim,now);
size[now]+=size[aim];
if(size[aim]>size[son[now]])son[now]=aim;
}
}
}
void dfs2(int now,int start){
top[now]=start;
dfsn[now]=++cnt_dfsn;
if(son[now])dfs2(son[now],start);
for(int i=head[now];i;i=h[i].next){
int aim=h[i].to;
if(aim!=fa[now] && aim!=son[now]){
dfs2(aim,aim);
}
}
}
signed main(){
scanf("%lld %lld",&n,&q);
inv=quick(n,mod-2);
for(int x,y,i=1;i<n;i++)scanf("%lld %lld",&x,&y),add(x,y);
dfs1(1,1),dfs2(1,1);
fa[1]=0;
for(int op,x,y,i=1;i<=q;i++){
scanf("%lld",&op);
if(op==1){
scanf("%lld %lld",&x,&y); //指定点与权
w[x]=(w[x]+y)%mod;
//对外面询问的贡献
ad(1,size[x]*y%mod);
ad(dfsn[x],(mod-size[x]*y%mod)%mod),ad(dfsn[x]+size[x],size[x]*y%mod);
//对内部(这里只修改本次通过重链爬上来的,轻边特判即可)
if(son[x])ad(dfsn[son[x]],(n-size[son[x]])*y%mod),ad(dfsn[son[x]]+size[son[x]],mod-(n-size[son[x]])*y%mod);
}else{
scanf("%lld",&x); //询问单点
ans=(sum(dfsn[x])+n*w[x]%mod)%mod;
for(int j=top[x];fa[j];j=top[fa[j]])ans=(ans+(n-size[j])*w[fa[j]]%mod)%mod;
printf("%lld\n",(ans*inv)%mod);
}
}
return 0;
}