树链剖分
模板
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 using namespace std; 7 inline int read() 8 { 9 char ch=getchar(); 10 int a=0,t=1; 11 while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();} 12 while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();} 13 return a*t; 14 } 15 inline long long readll() 16 { 17 char ch=getchar(); 18 long long a=0,t=1; 19 while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();} 20 while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();} 21 return a*t; 22 } 23 inline void write(int k){ 24 if (k<0) { 25 putchar('-'); 26 k=-k; 27 } 28 if (k>9) write(k/10); 29 putchar(k%10+'0'); 30 } 31 int n,m,r,num=0; 32 long long p; 33 int father[500005],dep[500005]={0},son_num[500005]; 34 int heavy_son[500005],id[500005],real[500005]; 35 long long top[500005]; 36 struct tree_arr{ 37 long long sum,tag,l,r; 38 }tree[500005]; 39 int head[500005],a[500005]; 40 struct edge_arr{ 41 int to,next; 42 }edge[500005]; 43 inline void lianshi(int u,int v){ 44 num++; edge[num].to=v; edge[num].next=head[u]; head[u]=num; 45 } 46 inline void dfs1(int now,int fa){ 47 father[now]=fa; 48 dep[now]=dep[father[now]]+1; 49 son_num[now]=1; 50 for (int i=head[now];i!=-1;i=edge[i].next){ 51 if (edge[i].to!=father[now]){ 52 dfs1(edge[i].to,now); 53 son_num[now]+=son_num[edge[i].to]; 54 if (heavy_son[now]<=0 || son_num[heavy_son[now]]<son_num[edge[i].to]){ 55 heavy_son[now]=edge[i].to; 56 } 57 } 58 } 59 } 60 int temp=0; 61 inline void dfs2(int now,int root){ 62 top[now]=root; 63 temp++; 64 id[now]=temp; 65 //printf("%d %d\n",now,id[now]); 66 real[id[now]]=now; 67 if (heavy_son[now]<=0) return; 68 dfs2(heavy_son[now],root); 69 for (int i=head[now];i!=-1;i=edge[i].next){ 70 if (edge[i].to!=father[now] && edge[i].to!=heavy_son[now]){ 71 dfs2(edge[i].to,edge[i].to); 72 } 73 } 74 } 75 inline void buildtree(int root,int l,int r){ 76 tree[root].l=l; tree[root].r=r; 77 if (l==r){ 78 tree[root].sum=a[real[l]]; return; 79 } 80 int mid=(l+r)>>1; 81 buildtree(root*2,l,mid); 82 buildtree(root*2+1,mid+1,r); 83 tree[root].sum=tree[root*2].sum+tree[root*2+1].sum; 84 } 85 inline void push_down(int root){ 86 tree[root*2].tag+=tree[root].tag; 87 tree[root*2].sum+=tree[root].tag*(tree[root*2].r-tree[root*2].l+1); 88 tree[root*2+1].tag+=tree[root].tag; 89 tree[root*2+1].sum+=tree[root].tag*(tree[root*2+1].r-tree[root*2+1].l+1); 90 tree[root].tag=0; 91 } 92 inline void addall(int root,int l,int r,long long x){ 93 if (l>tree[root].r || r<tree[root].l) return; 94 if (l<=tree[root].l && r>=tree[root].r){ 95 tree[root].tag+=x; tree[root].sum+=x*(tree[root].r-tree[root].l+1); 96 return; 97 } 98 push_down(root); 99 int mid=(tree[root].l+tree[root].r)>>1; 100 if (r<=mid) addall(root*2,l,r,x); 101 else if (l>mid) addall(root*2+1,l,r,x); 102 else addall(root*2,l,mid,x),addall(root*2+1,mid+1,r,x); 103 tree[root].sum=tree[root*2].sum+tree[root*2+1].sum; 104 } 105 inline void change(int u,int v,long long x){ 106 int zuxian_u=top[u],zuxian_v=top[v]; 107 while (zuxian_u!=zuxian_v){ 108 if (dep[zuxian_u]<dep[zuxian_v]){ 109 swap(u,v); swap(zuxian_u,zuxian_v); 110 } 111 addall(1,id[zuxian_u],id[u],x); 112 u=father[zuxian_u]; zuxian_u=top[u]; 113 } 114 if (dep[u]>dep[v]){ 115 swap(u,v); 116 } 117 addall(1,id[u],id[v],x); 118 } 119 inline long long findsum(int root,int l,int r){ 120 if (l>tree[root].r || r<tree[root].l) return 0; 121 if (l<=tree[root].l && r>=tree[root].r){ 122 return tree[root].sum; 123 } 124 push_down(root); 125 int mid=(tree[root].l+tree[root].r)>>1; 126 if (r<=mid) return findsum(root*2,l,r); 127 else if (l>mid) return findsum(root*2+1,l,r); 128 else return findsum(root*2,l,mid)+findsum(root*2+1,mid+1,r); 129 } 130 inline long long findans(int u,int v){ 131 long long sum=0; int zuxian_u=top[u],zuxian_v=top[v]; 132 while (zuxian_u!=zuxian_v){ 133 if (dep[zuxian_u]<dep[zuxian_v]){ 134 swap(u,v); swap(zuxian_u,zuxian_v); 135 } 136 sum+=findsum(1,id[zuxian_u],id[u]); 137 sum%=p; 138 u=father[zuxian_u]; 139 zuxian_u=top[u]; 140 } 141 if (dep[u]>dep[v]){ 142 swap(u,v); 143 } 144 sum+=findsum(1,id[u],id[v]); 145 sum%=p; 146 return sum; 147 } 148 int main(){ 149 n=read(),m=read(),r=read(),p=readll(); 150 for (int i=1;i<=n;i++) a[i]=read(),head[i]=-1; 151 for (int i=1;i<n;i++){ 152 int u=read(),v=read(); lianshi(u,v); lianshi(v,u); 153 } 154 dep[0]=0; son_num[0]=-1; 155 dfs1(r,0); 156 dfs2(r,r); 157 /*for (int i=1;i<=n;i++){ 158 printf("%d %d %d %d %d %d %d\n",i,father[i],dep[i],son_num[i],heavy_son[i],top[i],id[i]); 159 } 160 return 0;*/ 161 162 buildtree(1,1,temp); 163 164 for (int i=1;i<=m;i++){ 165 int k=read(); 166 if (k==1){ 167 int x=read(),y=read(),z=readll(); change(x,y,z); 168 } 169 if (k==2){ 170 int x=read(),y=read(); printf("%lld\n",findans(x,y)%p); 171 } 172 if (k==3){ 173 int x=read(),y=readll(); addall(1,id[x],id[x]+son_num[x]-1,y); 174 } 175 if (k==4){ 176 int x=read(); printf("%lld\n",findsum(1,id[x],id[x]+son_num[x]-1)%p); 177 } 178 } 179 return 0; 180 }
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>using namespace std;inline int read(){ char ch=getchar(); int a=0,t=1; while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();} while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();} return a*t;}inline long long readll(){ char ch=getchar(); long long a=0,t=1; while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();} while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();} return a*t;}inline void write(int k){if (k<0) {putchar('-');k=-k;}if (k>9) write(k/10);putchar(k%10+'0');}int n,m,r,num=0;long long p;int father[500005],dep[500005]={0},son_num[500005];int heavy_son[500005],id[500005],real[500005];long long top[500005];struct tree_arr{long long sum,tag,l,r;}tree[500005];int head[500005],a[500005];struct edge_arr{int to,next;}edge[500005];inline void lianshi(int u,int v){num++; edge[num].to=v; edge[num].next=head[u]; head[u]=num;}inline void dfs1(int now,int fa){father[now]=fa; dep[now]=dep[father[now]]+1;son_num[now]=1;for (int i=head[now];i!=-1;i=edge[i].next){if (edge[i].to!=father[now]){dfs1(edge[i].to,now);son_num[now]+=son_num[edge[i].to];if (heavy_son[now]<=0 || son_num[heavy_son[now]]<son_num[edge[i].to]){heavy_son[now]=edge[i].to;}}}}int temp=0;inline void dfs2(int now,int root){top[now]=root;temp++; id[now]=temp; //printf("%d %d\n",now,id[now]);real[id[now]]=now;if (heavy_son[now]<=0) return;dfs2(heavy_son[now],root);for (int i=head[now];i!=-1;i=edge[i].next){if (edge[i].to!=father[now] && edge[i].to!=heavy_son[now]){dfs2(edge[i].to,edge[i].to);}}}inline void buildtree(int root,int l,int r){tree[root].l=l; tree[root].r=r;if (l==r){tree[root].sum=a[real[l]]; return;}int mid=(l+r)>>1;buildtree(root*2,l,mid); buildtree(root*2+1,mid+1,r);tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;}inline void push_down(int root){tree[root*2].tag+=tree[root].tag; tree[root*2].sum+=tree[root].tag*(tree[root*2].r-tree[root*2].l+1);tree[root*2+1].tag+=tree[root].tag; tree[root*2+1].sum+=tree[root].tag*(tree[root*2+1].r-tree[root*2+1].l+1);tree[root].tag=0;}inline void addall(int root,int l,int r,long long x){if (l>tree[root].r || r<tree[root].l) return;if (l<=tree[root].l && r>=tree[root].r){tree[root].tag+=x; tree[root].sum+=x*(tree[root].r-tree[root].l+1);return;}push_down(root);int mid=(tree[root].l+tree[root].r)>>1;if (r<=mid) addall(root*2,l,r,x);else if (l>mid) addall(root*2+1,l,r,x); else addall(root*2,l,mid,x),addall(root*2+1,mid+1,r,x);tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;}inline void change(int u,int v,long long x){int zuxian_u=top[u],zuxian_v=top[v];while (zuxian_u!=zuxian_v){if (dep[zuxian_u]<dep[zuxian_v]){swap(u,v); swap(zuxian_u,zuxian_v);}addall(1,id[zuxian_u],id[u],x);u=father[zuxian_u]; zuxian_u=top[u];}if (dep[u]>dep[v]){swap(u,v);}addall(1,id[u],id[v],x);}inline long long findsum(int root,int l,int r){if (l>tree[root].r || r<tree[root].l) return 0;if (l<=tree[root].l && r>=tree[root].r){return tree[root].sum;}push_down(root);int mid=(tree[root].l+tree[root].r)>>1;if (r<=mid) return findsum(root*2,l,r);else if (l>mid) return findsum(root*2+1,l,r); else return findsum(root*2,l,mid)+findsum(root*2+1,mid+1,r);}inline long long findans(int u,int v){long long sum=0; int zuxian_u=top[u],zuxian_v=top[v];while (zuxian_u!=zuxian_v){if (dep[zuxian_u]<dep[zuxian_v]){swap(u,v); swap(zuxian_u,zuxian_v);}sum+=findsum(1,id[zuxian_u],id[u]);sum%=p; u=father[zuxian_u];zuxian_u=top[u];}if (dep[u]>dep[v]){swap(u,v);}sum+=findsum(1,id[u],id[v]);sum%=p;return sum;}int main(){ n=read(),m=read(),r=read(),p=readll();for (int i=1;i<=n;i++) a[i]=read(),head[i]=-1;for (int i=1;i<n;i++){int u=read(),v=read(); lianshi(u,v); lianshi(v,u);} dep[0]=0; son_num[0]=-1;dfs1(r,0); dfs2(r,r);/*for (int i=1;i<=n;i++){printf("%d %d %d %d %d %d %d\n",i,father[i],dep[i],son_num[i],heavy_son[i],top[i],id[i]);}return 0;*/buildtree(1,1,temp);for (int i=1;i<=m;i++){int k=read();if (k==1){int x=read(),y=read(),z=readll(); change(x,y,z);}if (k==2){int x=read(),y=read(); printf("%lld\n",findans(x,y)%p);}if (k==3){int x=read(),y=readll(); addall(1,id[x],id[x]+son_num[x]-1,y);}if (k==4){int x=read(); printf("%lld\n",findsum(1,id[x],id[x]+son_num[x]-1)%p);}}return 0;}