易错点:
-
比较top深度而不是自己(炫富就看家庭背景).
#include<cstdio> #include<iostream> using namespace std; const int MAXN=2e5,MAXM=2e5; struct Edge{ int from,to,nxt; }e[MAXM]; int head[MAXN],edgeCnt=1; void addEdge(int u,int v){ e[++edgeCnt].from=u; e[edgeCnt].to=v; e[edgeCnt].nxt=head[u]; head[u]=edgeCnt; } struct Node{ int ls,rs; long long lazy,sum; }tr[MAXN*4]; int nodeCnt=0; void insert(int &now,int l,int r,int ll,int rr,long long val){ if(!now)now=++nodeCnt; int b=min(r,rr)-max(l,ll)+1; tr[now].sum+=val*b; if(l>=ll&&r<=rr){ tr[now].lazy+=val; return; } int mid=(l+r)>>1; if(ll<=mid)insert(tr[now].ls,l,mid,ll,rr,val); if(rr>mid)insert(tr[now].rs,mid+1,r,ll,rr,val); } long long query(int now,int l,int r,int ll,int rr){//求和 if(l>=ll&&r<=rr){ return tr[now].sum; } int mid=(l+r)>>1; if(tr[now].lazy){ if(!tr[now].ls)tr[now].ls=++nodeCnt; tr[tr[now].ls].lazy+=tr[now].lazy; tr[tr[now].ls].sum+=tr[now].lazy*(mid-l+1); if(!tr[now].rs)tr[now].rs=++nodeCnt; tr[tr[now].rs].lazy+=tr[now].lazy; tr[tr[now].rs].sum+=tr[now].lazy*(r-mid); tr[now].lazy=0; } long long ans=0; if(ll<=mid)ans+=query(tr[now].ls,l,mid,ll,rr); if(rr>mid)ans+=query(tr[now].rs,mid+1,r,ll,rr); return ans; } int root=0; int siz[MAXN],son[MAXN]; int fa[MAXN]; int dep[MAXN]; void dfs1(int x){ siz[x]=1; dep[x]=dep[fa[x]]+1; for(int i=head[x];i;i=e[i].nxt){ int nowV=e[i].to; if(!siz[nowV]){ fa[nowV]=x; dfs1(nowV); siz[x]+=siz[nowV]; if(siz[nowV]>siz[son[x]]){ son[x]=nowV; } } } } int num[MAXN],numCnt=0; int pointValue[MAXN];//每个点的原始权值 int top[MAXN]; void dfs2(int x){ num[x]=++numCnt; insert(root,1,MAXN,num[x],num[x],pointValue[x]); if(x==son[fa[x]])top[x]=top[fa[x]]; else top[x]=x; if(son[x])dfs2(son[x]); for(int i=head[x];i;i=e[i].nxt){ int nowV=e[i].to; if(!num[nowV]) dfs2(nowV); } } void modify(int x,int y,int val){//x到y的所有结点加值 while(top[x]!=top[y]){ if(dep[top[x]]>dep[top[y]])swap(x,y); insert(root,1,MAXN,num[top[y]],num[y],val); y=fa[top[y]]; } if(num[x]>num[y])swap(x,y); insert(root,1,MAXN,num[x],num[y],val); } int p;//取模 long long sum(int x,int y){//求x到y的所有结点值之和 long long ans=0; while(top[x]!=top[y]){ if(dep[top[x]]>dep[top[y]])swap(x,y); ans+=query(root,1,MAXN,num[top[y]],num[y]); ans%=p; y=fa[top[y]]; } ans+=query(root,1,MAXN,min(num[x],num[y]),max(num[x],num[y])); ans%=p; return ans; } int main(){ int n,m,r; cin>>n>>m>>r>>p; for(int i=1;i<=n;i++){ scanf("%d",&pointValue[i]); } for(int i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); addEdge(x,y); addEdge(y,x); } dfs1(r); dfs2(r); for(int i=1;i<=m;i++){ int opt; cin>>opt; if(opt==1){ int x,y,z; scanf("%d%d%d",&x,&y,&z); modify(x,y,z); }else if(opt==2){ int x,y; scanf("%d%d",&x,&y); printf("%lld\n",sum(x,y)%p); }else if(opt==3){ int x,z; scanf("%d%d",&x,&z); insert(root,1,MAXN,num[x],num[x]+siz[x]-1,z); }else if(opt==4){ int x; scanf("%d",&x); printf("%lld\n",query(root,1,MAXN,num[x],num[x]+siz[x]-1)%p); } } return 0; }