【模板】树链剖分

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=200005;
inline int read()
{
 int X=0; bool flag=1; char ch=getchar();
 while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
 while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
 if(flag) return X;
 return ~(X-1);
}
int n,m,rt,mod,a[N],b[N];
int head[N],nxt[N],to[N],_cnt;
int siz[N],fa[N],dep[N],son[N],tp[N],dfn[N],rnk[N],num;
void add(int x,int y) {
 to[++_cnt]=y,nxt[_cnt]=head[x],head[x]=_cnt;
}
struct SegmentTree {
 int sum,len,dat; 
}t[N<<4];
void popup(int p) {
 t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
} 
void pushdown(int p) {
 t[p*2].sum=(t[p*2].sum+t[p].dat*t[p*2].len%mod)%mod;
 t[p*2+1].sum=(t[p*2+1].sum+t[p].dat*t[p*2+1].len%mod)%mod;
 t[p*2].dat=(t[p*2].dat+t[p].dat)%mod;
 t[p*2+1].dat=(t[p*2+1].dat+t[p].dat)%mod;
 t[p].dat=0;
}
void build(int p,int l,int r) {
 t[p].len=r-l+1;
 if(l==r) {
  t[p].sum=a[l];
  return;
 }
 int mid=(l+r)>>1;
 build(p*2,l,mid); build(p*2+1,mid+1,r);
 popup(p);
}
int query(int p,int l,int r,int ql,int qr) {
 if(ql<=l&&r<=qr) return t[p].sum;
 pushdown(p);
 int mid=(l+r)>>1,ans=0;
 if(ql<=mid) ans=(ans+query(p*2,l,mid,ql,qr))%mod;
 if(mid<qr) ans=(ans+query(p*2+1,mid+1,r,ql,qr))%mod;
 return ans;
}
void update(int p,int l,int r,int ql,int qr,int x) {
 if(ql<=l&&r<=qr) {
  t[p].dat=(t[p].dat+x)%mod; t[p].sum=(t[p].sum+t[p].len*x%mod)%mod;
  return;
 }
 pushdown(p);
 int mid=(l+r)>>1;
 if(ql<=mid) update(p*2,l,mid,ql,qr,x);
 if(mid<qr) update(p*2+1,mid+1,r,ql,qr,x);
 popup(p);
}
void dfs1(int x,int fath,int deep) {
 dep[x]=deep,fa[x]=fath,siz[x]=1;
 int maxson=-1;
 for(int i=head[x];i;i=nxt[i]) {
  int y=to[i];
  if(y==fath) continue;
     dfs1(y,x,deep+1);
     siz[x]+=siz[y];
     if(siz[y]>maxson) maxson=siz[y],son[x]=y;
 }
}
void dfs2(int x,int topf) {
 dfn[x]=++num,a[num]=b[x],tp[x]=topf; //pay attention
 if(!son[x]) return;
 dfs2(son[x],topf);
 for(int i=head[x];i;i=nxt[i]) {
  int y=to[i];
  if(!dfn[y]) dfs2(y,y);
 }
}
int querysum(int x,int y) {
 int ans=0,fx=tp[x],fy=tp[y];
 while(fx!=fy) {
  if(dep[fx]>=dep[fy]) ans=(ans+query(1,1,n,dfn[fx],dfn[x])),x=fa[fx];
  else ans=(ans+query(1,1,n,dfn[fy],dfn[y]))%mod,y=fa[fy];
  fx=tp[x],fy=tp[y];
 }
 if(dfn[x]<dfn[y]) ans=(ans+query(1,1,n,dfn[x],dfn[y]))%mod;
 else ans=(ans+query(1,1,n,dfn[y],dfn[x]))%mod;
 return ans;
}
void queryadd(int x,int y,int z) {
 int fx=tp[x],fy=tp[y];
 while(fx!=fy) {
  if(dep[fx]>=dep[fy]) update(1,1,n,dfn[fx],dfn[x],z),x=fa[fx];
  else update(1,1,n,dfn[fy],dfn[y],z),y=fa[fy];
  fx=tp[x],fy=tp[y];
 }
 if(dfn[x]<dfn[y]) update(1,1,n,dfn[x],dfn[y],z);
 else update(1,1,n,dfn[y],dfn[x],z);
}
signed main() {
 n=read(),m=read(),rt=read(),mod=read();
 for(int i=1;i<=n;i++) b[i]=read()%mod;
 for(int i=1;i<n;i++) {
  int x=read(),y=read();
  add(x,y),add(y,x);
 }
 dfs1(rt,0,1); dfs2(rt,rt);
 build(1,1,n);
 for(int i=1;i<=m;i++) {
  int type=read();
  if(type==1) {
   int x=read(),y=read(),z=read();
   queryadd(x,y,z%mod);
  }
  else if(type==2) {
   int x=read(),y=read();
   printf("%lld\n",querysum(x,y));
  }
  else if(type==3) {
   int x=read(),z=read();
   update(1,1,n,dfn[x],dfn[x]+siz[x]-1,z%mod);
  }
  else if(type==4) {
   int x=read();
   printf("%lld\n",query(1,1,n,dfn[x],dfn[x]+siz[x]-1));
  }
 }
 
}
posted @ 2021-01-02 18:59  仰望星空的蚂蚁  阅读(7)  评论(0)    收藏  举报  来源