社区讨论
10pts玄关求条,孩子真的没招了!
P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mi65rg7g
- 此快照首次捕获于
- 2025/11/19 23:29 3 个月前
- 此快照最后确认于
- 2025/11/21 00:00 3 个月前
能想到的所有坑全填了,有神犇能调下吗
CPP#include<bits/stdc++.h>
using namespace std;
const int N=100001;
int n,q,tot=0,now=0,mod,root;
struct egde{
int to,nxt;
}e[N<<1];
vector<long long>sum(N<<2),add(N<<2),v(N);
vector<int>dfn(N),rnk(N),fa(N),top(N),siz(N),dep(N),son(N),head(N);
void add1(int u,int w){
e[++tot].to=w;
e[tot].nxt=head[u];
head[u]=tot;
}
int dfs1(int u,int f){
siz[u]=1;
int p=0;
for(int i=head[u];i;i=e[i].nxt){
int to=e[i].to;
if(to==f)continue;
fa[to]=u;
dep[to]=dep[u]+1;
siz[u]+=dfs1(to,u);
if(siz[p]<siz[to])p=to;
}
son[u]=p;
return siz[u];
}
void dfs2(int u,int tp){
dfn[++now]=u;
rnk[u]=now;
top[u]=tp;
int heavy=son[u];
if(heavy!=0&&heavy!=fa[u])dfs2(heavy,tp);
for(int i=head[u];i;i=e[i].nxt){
int to=e[i].to;
if(to==fa[u]||to==heavy)continue;
dfs2(to,to);
}
}
void build(int k,int l,int r){
if(l==r){
sum[k]=(1LL*v[rnk[l]]%mod+mod)%mod;
return;
}
int mid=l+(r-l)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
}
void pushdown(int k,int l,int r){
if(!add[k])return;
int mid=l+(r-l)/2;
sum[k<<1]=(sum[k<<1]+1LL*add[k]*(mid-l+1))%mod;
add[k<<1]=(add[k<<1]+add[k])%mod;
sum[k<<1|1]=(sum[k<<1|1]+1LL*add[k]*(r-mid))%mod;
add[k<<1|1]=(add[k<<1|1]+add[k])%mod;
add[k]=0;
}
void change(int k,int l,int r,int x,int y,int z){
if(x<=l && r<=y){
z=(1LL*z%mod+mod)%mod;
add[k]=(add[k]+z)%mod;
sum[k]=(sum[k]+1LL*z*(r-l+1))%mod;
return;
}
pushdown(k,l,r);
int mid=l+(r-l)/2;
if(x<=mid)change(k<<1,l,mid,x,y,z);
if(y>mid)change(k<<1|1,mid+1,r,x,y,z);
sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
}
long long seek(int k,int l,int r,int x,int y){
if(x<=l&&r<=y)return sum[k]%mod;
pushdown(k,l,r);
int mid=l+(r-l)/2;
long long res=0;
if(x<=mid)res=(res+seek(k<<1,l,mid,x,y))%mod;
if(y>mid)res=(res+seek(k<<1|1,mid+1,r,x,y))%mod;
return res;
}
long long solve(int a,int b){
long long res=0;
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]])swap(a,b);
res=(res+seek(1,1,n,dfn[top[a]],dfn[a]))%mod;
a=fa[top[a]];
}
if(dep[a]>dep[b])swap(a,b);
res=(res+seek(1,1,n,dfn[a],dfn[b]))%mod;
return res;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
scanf("%d%d%d%d",&n,&q,&root,&mod);
for(int i=1;i<=n;i++){
scanf("%lld",&v[i]);
v[i]=(1LL*v[i]%mod+mod)%mod;
}
for(int i=1;i<n;i++){
int u,w;
scanf("%d%d",&u,&w);
add1(u,w);
add1(w,u);
}
dep[root]=1;
fa[root]=-1;
dfs1(root,-1);
dfs2(root,root);
build(1,1,n);
while(q--){
int opt;
scanf("%d",&opt);
if(opt==1){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
change(1,1,n,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
change(1,1,n,dfn[x],dfn[y],z);
}
else if(opt==2){
int x,y;
scanf("%d%d",&x,&y);
printf("%lld\n",(solve(x,y)+mod)%mod);
}
else if(opt==3){
int x,z;
scanf("%d%d",&x,&z);
change(1,1,n,dfn[x],dfn[x]+siz[x]-1,z);
}
else if(opt==4){
int x;
scanf("%d",&x);
printf("%lld\n",(seek(1,1,n,dfn[x],dfn[x]+siz[x]-1)+mod)%mod);
}
}
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...