zhangzhihao2 @ 2024-08-14 22:53:52
rt,求调 (要不是快23点了我还能再战2小时
#include<bits/stdc++.h>
#define int long long
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;
int n,m,rt,mod,tot,dfn[100009],hs[100009],tp[100009],f[100009],siz[100009],arr[100009],dep[100009];
int sum[400009],tag[400009],tree[100009];
vector<int> to[100009];
void dfs_n(int u,int fa){
siz[u]=1;
f[u]=fa;
dep[u]=dep[fa]+1;
for(int i=0;i<to[u].size();i++){
int v=to[u][i];
if(v==fa) continue;
dfs_n(v,u);
if(siz[v]>siz[hs[u]]) hs[u]=v;
siz[u]+=siz[v];
}
}
void sep(int u,int top){
dfn[u]=++tot;
tp[u]=top;
tree[tot]=arr[u];
if(!hs[u]) return;
sep(hs[u],top);
for(int i=0;i<to[u].size();i++){
int v=to[u][i];
if(v==f[u]||v==hs[u]) continue;
else sep(v,v);
}
}
void septree(){
dfs_n(rt,0);
sep(rt,rt);
}
void ff(int x,int l,int r,int k){
(sum[x]+=(r-l+1)*k)%=mod;
(tag[x]+=k)%=mod;
}
void pushdown(int x,int l,int r){
ff(ls,l,mid,tag[x]);
ff(rs,mid+1,r,tag[x]);
tag[x]=0;
}
void pushup(int x){
sum[x]=(sum[ls]+sum[rs])%mod;
}
void build(int x,int l,int r){
if(l==r){
sum[x]=tree[l]%mod;
return;
}
build(ls,l,mid);build(rs,mid+1,r);
pushup(x);
}
void add(int x,int l,int r,int ql,int qr,int k){
if(l>=ql&&r<=qr){
ff(x,l,r,k);
return;
}
// cout<<l<<' '<<r<<endl;
pushdown(x,l,r);
if(ql<=mid) add(ls,l,mid,ql,qr,k);
if(qr>mid) add(rs,mid+1,r,ql,qr,k);
pushup(x);
}
int query(int x,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr) return sum[x];
int res=0;
pushdown(x,l,r);
if(ql<=mid) (res+=query(ls,l,mid,ql,qr))%=mod;
if(qr>mid) (res+=query(rs,mid+1,r,ql,qr))%=mod;
return res;
}
int query_path(int u,int v){
int ans=0;
while(tp[u]!=tp[v]){
if(dep[u]<dep[v]) swap(u,v);
int res=query(1,1,n,dfn[tp[u]],dfn[u]);
(ans+=res)%=mod;
u=f[tp[u]];
}
if(dep[u]<dep[v]) swap(u,v);
(ans+=query(1,1,n,dfn[v],dfn[u]))%=mod;
return ans;
}
int query_tree(int u){
return query(1,1,n,dfn[u],dfn[u]+siz[u]-1);
}
void add_path(int u,int v,int k){
while(tp[u]!=tp[v]){
if(dep[u]<dep[v]) swap(u,v);
add(1,1,n,dfn[tp[u]],dfn[u],k);
// cout<<"**"<<dfn[tp[u]]<<' '<<dfn[u]<<endl;
u=f[tp[u]];
}
if(dep[u]<dep[v]) swap(u,v);
add(1,1,n,dfn[v],dfn[u],k);
}
void add_tree(int u,int k){
add(1,1,n,dfn[u],dfn[u]+siz[u]-1,k);
}
signed main(){
cin>>n>>m>>rt>>mod;
for(int i=1;i<=n;i++) cin>>arr[i];
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
to[a].push_back(b);
to[b].push_back(a);
}
septree();
build(1,1,n);
for(int i=1;i<=m;i++){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
add_path(x,y,z);
}
else if(op==2){
cin>>x>>y;
cout<<query_path(x,y)<<endl;
}
else if(op==3){
cin>>x>>y;
add_tree(x,y);
}
else{
cin>>x;
cout<<query_tree(x)<<endl;
}
// for(int j=1;j<=n;j++) cout<<query(1,1,n,j,j)<<' ';
// cout<<endl;
}
// cout<<query(1,1,n,1,1)<<endl;
// for(int i=1;i<=n;i++) cout<<tp[i]<<' ';
// cout<<endl;
// for(int i=1;i<=n;i++) cout<<dfn[i]<<' ';
// for(int i=1;i<=m;i++){
// for(int j=1;j<=n;j++){
// cout<<query(1,1,n,j,j)<<' ';
// }
// int a,b;
// cin>>a>>b;
// add(1,1,n,a,b,1);
// }
// for(int i=1;i<=n;i++){
// cout<<query(1,1,n,i,i)<<' ';
// }
return 0;
}
友情提醒:vscode运行#4数据报错在函数 ff()
,疑似参数 x 过大(我也不太懂,可能是无效线索
by zhangzhihao2 @ 2024-08-14 22:54:27
玄关玄关球球了救救孩子吧(嚎啕大哭
by rui_er @ 2024-08-14 22:57:37
@zhangzhihao2 路径改/查,应该比较重链顶端的 dep 而不是节点的 dep:考察一条链,在链顶挂一个叶子的情况
by zhangzhihao2 @ 2024-08-14 23:00:56
@rui_er 谢谢佬!!!
by zhangzhihao2 @ 2024-08-14 23:01:46
学习题解的时候看岔了,看来还是没有理解充分
by I_AK_CTSC @ 2024-08-15 08:31:49
@zhangzhihao2 线段树开4倍空间的
by I_AK_CTSC @ 2024-08-15 08:32:31
@rui_er 膜尺子
by I_AK_CTSC @ 2024-08-15 08:34:07
@zhangzhihao2
原来开到1e6了,没事了
by zhangzhihao2 @ 2024-08-15 08:40:39
@I_AK_CTSC 难崩了,本来以为只是因为数组开小了就一直往大了开
by I_AK_CTSC @ 2024-08-15 08:43:05
@zhangzhihao2 emm