树链剖分——简单而强大的数据维护方法
只是放个板子而已。
用我的码风覆盖了的。
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 }