树链剖分——简单而强大的数据维护方法
只是放个板子而已。
用我的码风覆盖了的。
1 #include<bits/stdc++.h>
2 using namespace std;
3 //------------------------------------------------------
4 inline int read(){
5 int f=1,x=0;
6 char c=getchar();
7 while(!isdigit(c)){
8 if(c=='-') f=-1;
9 c=getchar();
10 }
11 while(isdigit(c)){
12 x=x*10+c-'0';
13 c=getchar();
14 }
15 return x*f;
16 }
17 //------------------------------------------------------
18 const int N=2e5+10;
19 int at[N<<1],sum[N<<1];
20 int head[N],cnt,n,m,r,mod,tot,ans;
21 int w[N],dep[N],siz[N],fa[N],son[N],top[N],id[N],w2[N];
22 struct edge{ int to,next; }e[N<<1];
23 inline void addedge(int from,int to){ e[++cnt]=(edge){to,head[from]};head[from]=cnt; }
24 inline void add(int x,int y){addedge(x,y),addedge(y,x);}
25 //-------------------------------------------------------
26 void dfs1(int u,int f){
27 dep[u]=dep[f]+1;
28 siz[u]=1;
29 fa[u]=f;
30 int maxson=0;
31 for(int i=head[u];i;i=e[i].next){
32 int v=e[i].to;
33 if(v==f) continue;
34 dfs1(v,u);
35 siz[u]+=siz[v];
36 if(siz[v]>maxson) maxson=siz[v],son[u]=v;
37 }
38 }
39 void dfs2(int u,int f){
40 id[u]=++tot;
41 w2[tot]=w[u];
42 top[u]=f;
43 if(!son[u]) return;
44 dfs2(son[u],f);
45 for(int i=head[u];i;i=e[i].next){
46 int v=e[i].to;
47 if(v==fa[u]||v==son[u]) continue;
48 dfs2(v,v);
49 }
50 }
51 //-------------------------------------------------------
52 class Tree{
53 private:
54 inline int ls(int o){return o<<1;}
55 inline int rs(int o){return o<<1|1;}
56 inline void pushdown(int o,int l,int r){
57 if(!at[o]) return;
58 int mid=(l+r)>>1;
59 sum[ls(o)]=(sum[ls(o)]+at[o]*(mid-l+1))%mod;
60 sum[rs(o)]=(sum[rs(o)]+at[o]*(r-mid))%mod;
61 at[ls(o)]=(at[ls(o)]+at[o])%mod;
62 at[rs(o)]=(at[rs(o)]+at[o])%mod;
63 at[o]=0;
64 }
65 inline void pushup(int o){ sum[o]=(sum[ls(o)]+sum[rs(o)])%mod;}
66 public:
67 void build(int o,int l,int r){
68 if(l==r){
69 sum[o]=w2[l];
70 if(sum[o]>mod) sum[o]%=mod;
71 return;
72 }
73 int mid=(l+r)>>1;
74 build(ls(o),l,mid);
75 build(rs(o),mid+1,r);
76 pushup(o);
77 }
78 void change(int o,int l,int r,int x,int y,int k){
79 if(l>y||r<x) return;
80 if(x<=l&&r<=y){
81 sum[o]+=(r-l+1)*k;
82 at[o]+=k;
83 return;
84 }
85 int mid=(l+r)>>1;
86 pushdown(o,l,r);
87 if(x<=mid) change(ls(o),l,mid,x,y,k);
88 if(y>mid) change(rs(o),mid+1,r,x,y,k);
89 pushup(o);
90 }
91 void query(int o,int l,int r,int x,int y){
92 if(l>y||r<x) return;
93 if(x<=l&&r<=y){
94 ans+=sum[o];
95 ans%=mod;
96 return;
97 }
98 int mid=(l+r)>>1;
99 pushdown(o,l,r);
100 if(x<=mid) query(ls(o),l,mid,x,y);
101 if(y>mid) query(rs(o),mid+1,r,x,y);
102 }
103 inline int ask(int u,int v){
104 int cur=0;
105 while(top[u]!=top[v]){
106 if(dep[top[u]]<dep[top[v]]) swap(u,v);
107 ans=0;
108 query(1,1,n,id[top[u]],id[u]);
109 cur+=ans;
110 cur%=mod;
111 u=fa[top[u]];
112 }
113 ans=0;
114 if(dep[u]>dep[v]) swap(u,v);
115 query(1,1,n,id[u],id[v]);
116 cur+=ans;
117 return cur%mod;
118 }
119 inline void ask2(int u,int v,int k){
120 k%=mod;
121 while(top[u]!=top[v]){
122 if(dep[top[u]]<dep[top[v]]) swap(u,v);
123 change(1,1,n,id[top[u]],id[u],k);
124 u=fa[top[u]];
125 }
126 if(dep[u]>dep[v]) swap(u,v);
127 change(1,1,n,id[u],id[v],k);
128 }
129 }T;
130 //-------------------------------------------------------
131 int main(){
132 n=read();m=read();r=read();mod=read();
133 int k,x,y,z;
134 for(register int i=1;i<=n;i++) w[i]=read();
135 for(register int i=1;i<n;i++) add(read(),read());
136 dfs1(r,0);
137 dfs2(r,r);
138 T.build(1,1,n);
139 for(register int i=1;i<=m;i++){
140 k=read();
141 if(k==1){
142 x=read();y=read();z=read();
143 T.ask2(x,y,z);
144 }
145 else if(k==2){
146 x=read();y=read();
147 printf("%d\n",T.ask(x,y));
148 }
149 else if(k==3){
150 x=read();z=read();
151 T.change(1,1,n,id[x],id[x]+siz[x]-1,z);
152 }
153 else{
154 x=read();ans=0;
155 T.query(1,1,n,id[x],id[x]+siz[x]-1);
156 printf("%d\n",ans);
157 }
158 }
159 return 0;
160 }