



易错点:
比较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;
}
原文:https://www.cnblogs.com/zbsy-wwx/p/11734447.html