【模板】轻重链剖分
可以算是此题的进阶
题目描述
如题,已知一棵包含 N 个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:
操作 1: 格式: 1 x y z 表示将树从 x 到 y 结点最短路径上所有节点的值都加上 z。
操作 2: 格式: 2 x y 表示求树从 x 到 y 结点最短路径上所有节点的值之和。
操作 3: 格式: 3 x z 表示将以 x 为根节点的子树内所有节点值都加上 z。
操作 4: 格式: 4 x 表示求以 x 为根节点的子树内所有节点值之和
输入格式
第一行包含 4 个正整数 N,M,R,P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。
接下来一行包含 N 个非负整数,分别依次表示各个节点上初始的数值。
接下来 N−1 行每行包含两个整数 x,y,表示点 x 和点 y 之间连有一条边(保证无环且连通)。
接下来 M 行每行包含若干个正整数,每行表示一个操作,格式如下:
操作 1: 1 x y z;
操作 2: 2 x y;
操作 3: 3 x z;
操作 4: 4 x。
输出格式
输出包含若干行,分别依次表示每个操作 22 或操作 44 所得的结果(对 PP 取模)。
输入输出样例
输入 #1
5 5 2 24 7 3 7 8 0 1 2 1 5 3 1 4 1 3 4 2 3 2 2 4 5 1 5 1 3 2 1 3
输出 #1
2 21
说明/提示
数据规模:
对于 30% 的数据: 1≤N≤10,1≤M≤10;
对于 70% 的数据: 1≤N≤10^3,1≤M≤10^3;
对于 100% 的数据: 1≤N≤10^5,1≤M≤10^5,1≤R≤N,1≤P≤2^31−1。
样例说明:
树的结构如下:

各个操作如下:

故输出应依次为 2 和 21
有时间再解释吧,先放个代码
1 /* 2 5 5 2 24 3 7 3 7 8 0 4 1 2 5 1 5 6 3 1 7 4 1 8 3 4 2 9 3 2 2 10 4 5 11 1 5 1 3 12 2 1 3 13 */ 14 #include<iostream> 15 #include<cstring> 16 #include<cstdio> 17 #include<cmath> 18 using namespace std; 19 int dep[1000001]={0},dad[1000001]={0},size[1000001]={0},heavy_son[1000001]={0}; 20 int cnt=0,N,Mod,n,m,s; 21 int top[1000001]={0},last[1000001]={0},v[1000001]={0}; 22 int new_id[1000001]={0},old_id[1000001]={0},tree[1000001]={0},lazy[1000001]={0}; 23 struct node{ 24 int to,next; 25 }line[1000001]; 26 int add(int add_u,int add_v){ 27 line[++N].to=add_v; 28 line[N].next=last[add_u]; 29 last[add_u]=N; 30 } 31 int Max(int max_x,int max_y){ 32 if(max_x<max_y) return max_y; 33 return max_x; 34 } 35 int Min(int min_x,int min_y){ 36 if(min_x>min_y) return min_y; 37 return min_x; 38 } 39 int dfs1(int F,int root,int deep){ 40 dep[root]=deep; 41 dad[root]=F; 42 size[root]=1; 43 int maxn=0; 44 for(int i=last[root];i;i=line[i].next){ 45 int To=line[i].to; 46 if(F==To) continue; 47 dfs1(root,To,deep+1); 48 size[root]+=size[To]; 49 if(size[To]>maxn){ 50 heavy_son[root]=To; 51 maxn=size[To]; 52 } 53 } 54 return 0; 55 } 56 int dfs2(int F,int root,int Top){ 57 top[root]=Top; 58 new_id[root]=++cnt; 59 old_id[cnt]=root; 60 if(heavy_son[root]) dfs2(root,heavy_son[root],Top); 61 for(int i=last[root];i;i=line[i].next){ 62 int To=line[i].to; 63 if(F==To||heavy_son[root]==To) continue; 64 dfs2(root,To,To); 65 } 66 } 67 int build(int x,int l,int r){ 68 if(l==r){ 69 tree[x]=v[old_id[l]]%Mod; 70 return 0; 71 } 72 int mid=(l+r)/2; 73 build(x*2,l,mid); 74 build(x*2+1,mid+1,r); 75 tree[x]=(tree[x*2]+tree[x*2+1])%Mod; 76 } 77 int deal_lazy(int deal_fh,int deal_l,int deal_r,int deal_v){ 78 lazy[deal_fh]=(lazy[deal_fh]+deal_v)%Mod; 79 tree[deal_fh]=(tree[deal_fh]+((deal_r-deal_l+1)*deal_v%Mod))%Mod; 80 } 81 int push_down1(int fh,int ll,int rr){ 82 int mid=(ll+rr)/2; 83 deal_lazy(fh*2,ll,mid,lazy[fh]); 84 deal_lazy(fh*2+1,mid+1,rr,lazy[fh]); 85 lazy[fh]=0; 86 } 87 int total(int x,int l,int r,int b_l,int b_r){ 88 if(b_l<=l&&r<=b_r) return tree[x]; 89 push_down1(x,l,r); 90 int mid=(l+r)/2,ans=0; 91 if(b_l<=mid) ans=(ans+total(x*2,l,mid,b_l,b_r))%Mod; 92 if(mid+1<=b_r) ans=(ans+total(x*2+1,mid+1,r,b_l,b_r))%Mod; 93 return ans; 94 } 95 int turn(int x,int l,int r,int b_l,int b_r,int v){ 96 if(b_l<=l&&r<=b_r){ 97 tree[x]=(tree[x]+((r-l+1)*v%Mod))%Mod; 98 lazy[x]=(lazy[x]+v)%Mod; 99 return 0; 100 } 101 push_down1(x,l,r); 102 int mid=(l+r)/2; 103 if(b_l<=mid) turn(x*2,l,mid,b_l,b_r,v); 104 if(mid+1<=b_r) turn(x*2+1,mid+1,r,b_l,b_r,v); 105 tree[x]=(tree[x*2]+tree[x*2+1])%Mod; 106 return 0; 107 } 108 int course_1(int x,int y,int z){ 109 while(top[x]!=top[y]){ 110 if(dep[top[x]]>=dep[top[y]]){ 111 turn(1,1,n,new_id[top[x]],new_id[x],z); 112 x=dad[top[x]]; 113 } 114 else{ 115 turn(1,1,n,new_id[top[y]],new_id[y],z); 116 y=dad[top[y]]; 117 } 118 } 119 if(dep[x]<=dep[y]) turn(1,1,n,new_id[x],new_id[y],z); 120 else turn(1,1,n,new_id[y],new_id[x],z); 121 return 0; 122 123 } 124 int course_2(int x,int y){ 125 int ans=0; 126 while(top[x]!=top[y]){ 127 if(dep[top[x]]>=dep[top[y]]){ 128 ans=(ans+total(1,1,n,new_id[top[x]],new_id[x]))%Mod; 129 x=dad[top[x]]; 130 } 131 else{ 132 ans=(ans+total(1,1,n,new_id[top[y]],new_id[y]))%Mod; 133 y=dad[top[y]]; 134 } 135 } 136 if(dep[x]<=dep[y]) ans=(ans+total(1,1,n,new_id[x],new_id[y]))%Mod; 137 else ans=(ans+total(1,1,n,new_id[y],new_id[x]))%Mod; 138 return ans; 139 140 } 141 int main(){ 142 scanf("%d%d%d%d",&n,&m,&s,&Mod); 143 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 144 for(int i=1;i<=n-1;i++){ 145 int UU,VV; 146 scanf("%d%d",&UU,&VV); 147 add(UU,VV); 148 add(VV,UU); 149 } 150 dfs1(s,s,1); 151 dfs2(s,s,s); 152 build(1,1,n); 153 while(m--){ 154 int xh; 155 scanf("%d",&xh); 156 if(xh==1){ 157 int X,Y,Z; 158 scanf("%d%d%d",&X,&Y,&Z); 159 course_1(X,Y,Z); 160 continue; 161 } 162 if(xh==2){ 163 int X,Y; 164 scanf("%d%d",&X,&Y); 165 printf("%d\n",course_2(X,Y)); 166 continue; 167 } 168 if(xh==3){ 169 int R,VAL; 170 scanf("%d%d",&R,&VAL); 171 turn(1,1,n,new_id[R],new_id[R]+size[R]-1,VAL%Mod); 172 continue; 173 } 174 int R; 175 scanf("%d",&R); 176 printf("%d\n",total(1,1,n,new_id[R],new_id[R]+size[R]-1)); 177 } 178 }

浙公网安备 33010602011771号