树链剖分

来源:互联网 发布:怎样做软件开发 编辑:程序博客网 时间:2024/06/15 02:12

学了2天的树链剖分终于搞懂了,不容易啊~~~~(>_<)~~~~

洛谷的3384是一道很好的模板题

传送门:https://www.luogu.org/problem/show?pid=3384#sub

代码如下:

#include<iostream>#include<cstring>#include<string>#include<cmath>#include<cstdio>#include<algorithm>#define N 500005using namespace std;int n,m,R,P,x,y,z,t;long long d[N],ee[N],real[N];int heavyson[N],depth[N],head[N],id[N],father[N],son[N],b[N*4],c[N*4],a[N],top[N];struct Edge{int next,to;}e[N];int kk=0;void add(int x,int y){kk++;e[kk].next=head[x];e[kk].to=y;head[x]=kk;}void build(int k,int x,int y){b[k]=x; c[k]=y;if (x==y){d[k]=a[real[x]];return;}int mid=(x+y)/2;build(k*2,x,mid);build(k*2+1,mid+1,y);d[k]=d[k*2]+d[k*2+1];}void maintain(int k){ee[k*2]=ee[k*2]+ee[k];ee[k*2+1]=ee[k*2+1]+ee[k];d[k*2]=d[k*2]+ee[k]*(c[k*2]-b[k*2]+1);d[k*2+1]=d[k*2+1]+ee[k]*(c[k*2+1]-b[k*2+1]+1);ee[k]=0;}long long sum(int k,int x,int y){if (x==b[k]&&y==c[k]) return d[k];if (ee[k]) maintain(k);int mid=(b[k]+c[k])/2;if (y<=mid) return sum(k*2,x,y);if (x>mid) return sum(k*2+1,x,y);if (x<=mid&&y>mid) return sum(k*2+1,mid+1,y)+sum(k*2,x,mid);}void addd(int k,int x,int y,int z){if (x>c[k]||y<b[k]) return;if (x<=b[k]&&y>=c[k]){ee[k]=ee[k]+z;d[k]=d[k]+z*(c[k]-b[k]+1);return;}if (ee[k]) maintain(k);int mid=(b[k]+c[k])/2;if (y<=mid) addd(k*2,x,y,z);else if (x>mid) addd(k*2+1,x,y,z);else if (x<=mid&&y>mid){addd(k*2,x,mid,z);addd(k*2+1,mid+1,y,z);}d[k]=d[k*2]+d[k*2+1];return;}void Dfs1(int now,int fa){father[now]=fa;depth[now]=depth[fa]+1;son[now]=1;for (int i=head[now];i;i=e[i].next){if (e[i].to!=fa){Dfs1(e[i].to,now);son[now]=son[now]+son[e[i].to];if (heavyson[now]==0||son[e[i].to]>son[heavyson[now]]) heavyson[now]=e[i].to;}}}int temp=0;void Dfs2(int u,int first){top[u]=first;temp++;id[u]=temp;real[temp]=u;if (!heavyson[u]) return;Dfs2(heavyson[u],first);for (int i=head[u];i;i=e[i].next){int v=e[i].to;if (v!=heavyson[u]&&v!=father[u]) Dfs2(v,v);}}long long find(int u,int v){long long sum1=0;int tou=top[u];int tov=top[v];while (tou!=tov){if (depth[tou]<depth[tov]) swap(u,v),swap(tou,tov);sum1=sum1+sum(1,id[tou],id[u]);sum1=sum1%P;u=father[tou];tou=top[u];}if (depth[u]>depth[v]) swap(u,v);sum1=sum1+sum(1,id[u],id[v]);return sum1%P;}void change(int u,int v,int z){int tou=top[x];int tov=top[y];while (tou!=tov){if (depth[tou]<depth[tov]) swap(u,v),swap(tou,tov);addd(1,id[tou],id[u],z);u=father[tou];tou=top[u];}if (depth[u]>depth[v]) swap(u,v);addd(1,id[u],id[v],z);}int main(){scanf("%d%d%d%d",&n,&m,&R,&P);for (int i=1;i<=n;i++) scanf("%d",&a[i]);for (int i=1;i<n;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}Dfs1(R,0);Dfs2(R,R);build(1,1,n);for (int i=1;i<=m;i++){scanf("%d",&t);if (t==1){scanf("%d%d%d",&x,&y,&z);change(x,y,z);}if (t==2){scanf("%d%d",&x,&y);printf("%lld\n",find(x,y));}if (t==3){scanf("%d%d",&x,&y);addd(1,id[x],id[x]+son[x]-1,y);}if (t==4){scanf("%d",&x);printf("%lld\n",sum(1,id[x],id[x]+son[x]-1)%P); }}return 0;}


原创粉丝点击