功能:
修改与查询整个子树
修改与查询路径 可以时区间和 最大最小值 上同
求lca
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) #define lson l,m,pos<<1 #define rson m+1,r,pos<<1|1 typedef pair<int,int>pii; ////////////////////////////////// const int N=2e6+10; const int M=1e6; int t[N<<2],col[N<<2],w[N],n,mod,m,root,node[N]; void up(int pos) { t[pos]=t[pos<<1]+t[pos<<1|1];t[pos]%=mod; } void down(int m,int pos) { if(col[pos]) { col[pos<<1]+=col[pos]; col[pos<<1|1]+=col[pos]; t[pos<<1]+=(m-(m>>1))*col[pos];t[pos<<1]%=mod; t[pos<<1|1]+=(m>>1)*col[pos];t[pos<<1|1]%=mod; col[pos]=0; } } void build(int l,int r,int pos) { col[pos]=0; if(l==r){t[pos]=w[l]%mod;return ;}//w为重新编号的权值 int m=(l+r)>>1; build(lson);build(rson); up(pos); } void update(int L,int R,int x,int l,int r,int pos) { if(L<=l&&r<=R) { t[pos]+=x*(r-l+1);t[pos]%=mod;col[pos]+=x;return ; } down(r-l+1,pos); int m=(l+r)>>1; if(L<=m)update(L,R,x,lson); if(R>m)update(L,R,x,rson); up(pos); } int query(int L,int R,int l,int r,int pos) { int ans=0; if(L<=l&&r<=R)return t[pos]; down(r-l+1,pos); int m=(l+r)>>1; if(L<=m)ans+=query(L,R,lson),ans%=mod; if(R>m)ans+=query(L,R,rson),ans%=mod; up(pos); return ans; } /////////////////////////////// int dep[N],siz[N],fa[N],son[N],head[M],pos,id[N],top[N],cnt; struct Edge { int to,nex; }edge[M]; void add(int a,int b) { edge[++pos].nex=head[a]; edge[pos].to=b; head[a]=pos; } void dfs1(int x,int f,int deep) { dep[x]=deep; fa[x]=f; siz[x]=1; int maxson=-1; for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==f)continue; dfs1(v,x,deep+1); siz[x]+=siz[v]; if(siz[v]>maxson)maxson=siz[v],son[x]=v; } } void dfs2(int x,int topf) { id[x]=++cnt; w[cnt]=node[x]; top[x]=topf; if(!son[x])return; dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to; if(v==fa[x]||v==son[x])continue; dfs2(v,v); } } int qrange(int x,int y)//询问x到y最短路径的权值和 { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=query(id[top[x]],id[x],1,n,1); ans%=mod; x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans=(ans+query(id[x],id[y],1,n,1))%mod; return ans; } void updaterange(int x,int y,int k)//将x 到y的最短路径上加k { k%=mod; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); update(id[top[x]],id[x],k,1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); update(id[x],id[y],k,1,n,1); } int qson(int x)//询问以x为根结点的子树去权值和 { return query(id[x],id[x]+siz[x]-1,1,n,1); } void updateson(int x,int k)//将以x为根结点子树所有点的权值加k { update(id[x],id[x]+siz[x]-1,k,1,n,1); } int main() { cin>>n>>m>>root>>mod; rep(i,1,n)RI(node[i]); rep(i,1,n-1){int u,v;RII(u,v);add(u,v);add(v,u);} dfs1(root,0,1); dfs2(root,root); build(1,n,1); rep(i,1,m) { int k,x,y,z;RI(k); if(k==1) { RIII(x,y,z);updaterange(x,y,z); } else if(k==2) { RII(x,y);printf("%d ",qrange(x,y)); } else if(k==3) { RII(x,y);updateson(x,y); } else { RI(x);printf("%d ",qson(x)); } } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int getlca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y; }