树剖10分,求助

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

@[xiaolou](/space/show?uid=68675) 您犯了一个很常见的错误。。第二遍dfs的时候,应该用 ```cpp dfs2(v,v); ``` 而不是 ```cpp dfs2(v,u); ``` 还有就是第二遍dfs初始部分应该用 ```cpp dfs2(r,r); ```
by NaCly_Fish @ 2019-05-09 19:06:04


第二遍dfs是划分重链的,一个轻儿子必定为一个重链的顶点
by NaCly_Fish @ 2019-05-09 19:07:20


@[NaCly_Fish](/space/show?uid=115864) 按您说的改了,然后样例Re了 ```cpp #include <bits/stdc++.h> using namespace std; #define int long long int n,m,R,k; int a[100005]; struct Node { int v; Node *next; }*h[100005],pool[200005]; struct SGTree { int sum,la,le,ri; }t[400005]; int top[100005]; int son[100005]; int size[100005]; int w[100005]; int rw[100005]; int dep[100005]; int f[100005]; int cnt=0,tot=0; void Adde(int u,int v) { Node *p=&pool[++tot]; p->v=v; p->next=h[u]; h[u]=p; } void Dfs1(int u,int fa) { int maxsize=-1,maxson=0; size[u]=1; f[u]=fa; for(Node *p=h[u];p;p=p->next) { if(p->v!=fa) { dep[p->v]=dep[u]+1; Dfs1(p->v,u); if(maxsize<size[p->v]) { maxsize=size[p->v]; maxson=p->v; } size[u]+=size[p->v]; } } son[u]=maxson; } void Dfs2(int u,int fa) { cnt++; w[u]=cnt; if(son[u]) { top[son[u]]=top[u]; Dfs2(son[u],u); } for(Node *p=h[u];p;p=p->next) { if(p->v!=fa&&p->v!=son[u]) { top[p->v]=p->v; Dfs2(p->v,p->v); } } } void BuildT(int id,int l,int r) { t[id].le=l; t[id].ri=r; t[id].la=0; if(t[id].le==t[id].ri) { t[id].sum=a[rw[t[id].le]]/*a[rw[t[id].ri]]*/; return; } int M=(l+r)/2; BuildT(id*2,l,M); BuildT(id*2+1,M+1,r); t[id].sum=t[id*2].sum+t[id*2+1].sum; } void Change(int id,int l,int r,int c) { if(t[id].le==l&&t[id].ri==r) { t[id].la+=c; return; } if(t[id].la!=0) { t[id*2].la+=t[id].la; t[id*2].la%=k; t[id*2+1].la+=t[id].la; t[id*2+1].la%=k; t[id].la=0; } if(r<=t[id*2].ri) { Change(id*2,l,r,c); } else if(l>=t[id*2+1].le) { Change(id*2+1,l,r,c); } else { Change(id*2,l,t[id*2].ri,c); Change(id*2+1,t[id*2+1].le,r,c); } t[id].sum=(t[id*2].sum%k+t[id*2].la*(t[id*2].ri-t[id*2].le+1)%k+t[id*2+1].sum%k+t[id*2+1].la*(t[id*2+1].ri-t[id*2+1].le+1)%k)%k; } int Query(int id,int l,int r) { if(t[id].le==l&&t[id].ri==r) { return (t[id].sum+t[id].la*(t[id].ri-t[id].le+1)%k)%k; } if(t[id].la) { t[id*2].la+=t[id].la; t[id*2].la%=k; t[id*2+1].la+=t[id].la; t[id*2+1].la%=k; t[id].sum+=t[id].la*(t[id].ri-t[id].le+1); t[id].sum%=k; t[id].la=0; } if(r<=t[id*2].ri) { return Query(id*2,l,r)%k; } else if(l>=t[id*2+1].le) { return Query(id*2+1,l,r)%k; } else { return (Query(id*2,l,t[id*2].ri)%k+Query(id*2+1,t[id*2+1].le,r)%k)%k; } } int Ask(int x,int y) { int sum=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) { swap(x,y); } sum+=Query(1,w[top[x]],w[x]); sum%=k; x=f[top[x]]; } if(x!=y) { if(dep[x]>dep[y]) { swap(x,y); } sum+=Query(1,w[x],w[y]); sum%=k; } return sum%k; } void Modify(int x,int y,int z) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) { swap(x,y); } Change(1,w[top[x]],w[x],z); x=f[top[x]]; } if(x!=y) { if(dep[x]>dep[y]) { swap(x,y); } Change(1,w[x],w[y],z); } } signed main() { scanf("%lld%lld%lld%lld",&n,&m,&R,&k); for(int i=1;i<=n;++i) { scanf("%lld",&a[i]); } int uu,vv; for(int i=1;i<n;++i) { scanf("%lld%lld",&uu,&vv); Adde(uu,vv); Adde(vv,uu); } Dfs1(R,0); Dfs2(R,R); for(int i=1;i<=n;++i) { if(!top[i]) { top[i]=R; } } for(int i=1;i<=n;++i) { rw[w[i]]=i; } int op,x,y,z; BuildT(1,1,n); for(int i=1;i<=m;++i) { scanf("%lld%lld",&op,&x); if(op==1) { scanf("%lld%lld",&y,&z); Modify(w[x],w[y],z); } else if(op==2) { scanf("%lld",&y); printf("%lld\n",Ask(x,y)); } else if(op==3) { scanf("%lld",&y); Change(1,w[x],w[x]+size[x]-1,y); } else { printf("%lld\n",Query(1,w[x],w[x]+size[x]-1)); } } return 0; } ```
by xiaolou @ 2019-05-09 19:11:22


@[xiaolou](/space/show?uid=68675) 您这个写法太神奇了,我改不来。。
by NaCly_Fish @ 2019-05-09 19:39:17


@[NaCly_Fish](/space/show?uid=115864) emmm,很神奇吗
by xiaolou @ 2019-05-09 19:42:52


@[xiaolou](/space/show?uid=68675) 可能只是我和您的码风差异比较大吧。。 强行安利一下我的树剖blog:[Link](https://www.luogu.org/blog/NaCly-Fish-blog/qwqQAQ)
by NaCly_Fish @ 2019-05-09 19:44:30


@[NaCly_Fish](/space/show?uid=115864) orz神鱼
by lsy263 @ 2019-07-11 23:57:50


|