题解:P9527 [JOIST 2022] 洒水器 / Sprinkler
厉害的一道题。
将无根树变换为以
令
接下来考虑修改,发现
我们需要用
#include <bits/stdc++.h>
#define int long long
#define umap unordered_map
#define vint vector<int>
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define ull unsigned long long
#define uint unsigned int
#define rg register
#define il inline
#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 sqr(x) ((x)*(x))
using namespace std;
const int INF=0x3f3f3f3f;
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*f;
}
inline void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=200005,D=45;
int n,mod,h[N],fa[N],q;
vint G[N];
void dfs(int u,int f){
fa[u]=f;
for(auto v:G[u]){
if(v==f) continue;
dfs(v,u);
}
}
int tag[N][D];//以u为子树,距离恰好为D的节点需要*
signed main(){
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
cin>>n>>mod;
rep(i,1,n-1){
int u=read(),v=read();
G[u].push_back(v),G[v].push_back(u);
}
rep(i,1,n) rep(j,0,40) tag[i][j]=1;
dfs(1,0);
rep(i,1,n) h[i]=read();
cin>>q;
while(q--){
int op=read();
if(op==1){
int x=read(),d=read(),w=read();
while(x&&d>=0){
tag[x][d]=tag[x][d]*w%mod;
if(d>=1) tag[x][d-1]=tag[x][d-1]*w%mod;
if(x==1){
rep(i,0,d-2) tag[1][i]=tag[1][i]*w%mod;
}
x=fa[x],--d;
}
}
else{
int x=read(),res=h[x],d=0;
while(x&&d<=40){
res=res*tag[x][d]%mod;
++d;
x=fa[x];
}
cout<<res<<"\n";
}
}
#ifndef ONLINE_JUDGE
fprintf(stderr,"%f\n",1.0*clock()/CLOCKS_PER_SEC);
#endif
return 0;
}