蒟蒻10pts求调教

P3384 【模板】重链剖分/树链剖分

@[brother_jie](/user/754502) 6
by hegm @ 2023-05-11 15:33:50


你还没剖分就读入权值?
by hegm @ 2023-05-11 15:34:22


过了就给个关注吧![](//图.tk/2)
by hegm @ 2023-05-11 15:36:46


@[hegm](/user/331947) dalao还是10pts啊(悲 ``` #include<bits/stdc++.h> #define maxn 114514 #define ls root*2 #define rs root*2+1 using namespace std; struct node { int nxt,to; }e[maxn*2]; //----------线段树------------------- int n,m,r,p,a[maxn],w[maxn]; struct node1 { int l,r,val,f; }t[maxn*4]; void bld(int l,int r,int root) { t[root].l=l; t[root].r=r; if(l==r) { t[root].val=w[l]; t[root].val%=p; return; } int mid=(l+r)/2; bld(l,mid,root*2); bld(mid+1,r,root*2+1); t[root].val=(t[ls].val+t[rs].val)%p; } void down(int root) { t[ls].f+=t[root].f; t[rs].f+=t[root].f; t[ls].val=(t[ls].val+(t[ls].r-t[ls].l+1)*t[root].f)%p; t[rs].val=(t[rs].val+(t[rs].r-t[rs].l+1)*t[root].f)%p; t[root].f=0; } void add2(int x,int y,int root,int k) { if(t[root].l>=x&&t[root].r<=y) { t[root].val+=((t[root].r-t[root].l+1)*k)%p; t[root].f+=k; return; } if(t[root].f) down(root); int mid=(t[root].l+t[root].r)/2; if(x<=mid) add2(x,y,ls,k); if(y>mid) add2(x,y,rs,k); t[root].val=(t[ls].val+t[rs].val)%p; } int query(int x,int y,int root) { int ret=0; if(t[root].l>=x&&t[root].r<=y) return t[root].val; if(t[root].f) down(root); int mid=(t[root].l+t[root].r)/2; if(x<=mid) ret=(ret+query(x,y,ls))%p; if(y>mid) ret=(ret+query(x,y,rs))%p; return ret; } //----------------------------------- int head[maxn*2],cnt1; void add(int u,int v) { e[++cnt1].to=v; e[cnt1].nxt=head[u]; head[u]=cnt1; } int top[maxn],dfn[maxn],son[maxn],size[maxn],f[maxn],dep[maxn],cnt; void dfs1(int u,int fa) { size[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v!=fa) { dep[v]=dep[u]+1; f[v]=u; dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) son[u]=v; } } } void dfs2(int u,int t) { dfn[++cnt]=u; w[cnt]=a[u]; top[u]=t; if(son[u]) dfs2(son[u],t); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(v!=f[u]&&v!=son[u]) dfs2(v,v); } } int sum(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=(ans+query(dfn[top[x]],dfn[x],1))%p; x=f[top[x]]; } if(dep[x]>dep[y]) swap(x,y); ans=(ans+query(dfn[x],dfn[y],1))%p; return ans; } void add1(int x,int y,int z) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); add2(dfn[top[x]],dfn[x],1,z); x=f[top[x]]; } if(dep[x]>dep[y]) swap(x,y); add2(dfn[x],dfn[y],1,z); } int main() { cin>>n>>m>>r>>p; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<n;i++) { int x,y; cin>>x>>y; add(x,y); add(y,x); } dfs1(r,0); dfs2(r,r); bld(1,n,1); while(m--) { int op,x,y,z; cin>>op; if(op==1) { cin>>x>>y>>z; add1(x,y,z); } else if(op==2) { cin>>x>>y; cout<<sum(x,y)<<endl; } else if(op==3) { cin>>x>>z; add2(dfn[x],dfn[x]+size[x]-1,1,z); } else { cin>>x; cout<<(query(dfn[x],dfn[x]+size[x]-1,1))%p<<endl; } } } ```
by Darling_zero_two @ 2023-05-11 22:10:04


@[brother_jie](/user/754502) 你。。。。。你要不重新学一下树剖?
by hegm @ 2023-05-12 06:57:06


树剖上线段树维护的 $l\sim r$ 的区间,表示的是 $dfn$ 序在 $l\sim r$ 的点,不是编号啊!
by hegm @ 2023-05-12 07:00:31


@[hegm](/user/331947) dalao我就是维护的编号啊
by Darling_zero_two @ 2023-05-13 12:44:42


破案力,dfs2写错了
by Darling_zero_two @ 2023-05-13 14:38:43


@[hegm](/user/331947) 已关注
by Darling_zero_two @ 2023-05-13 14:40:29


|