版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/86768569
正题
题目大意
要求支持路径加和求和,子树加和求和
解题思路
树剖不解释
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200000;
int tot,cnt,n,m,s,p,ls[N],pw[N],id[N];
int siz[N],dep[N],f[N],son[N],seg[N],top[N];
struct treenode{
int l,r,lazy,val;
};
struct LineTree{
treenode t[N*2];
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r)
{
t[x].val=pw[id[l]]%p;
return;
}
int mid=(l+r)>>1;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
t[x].val=(t[x*2].val+t[x*2+1].val)%p;
}
void downdata(int x)
{
if(t[x].lazy)
{
(t[x*2].lazy+=t[x].lazy)%=p;
(t[x*2].val+=t[x].lazy*(t[x*2].r-t[x*2].l+1))%=p;
(t[x*2+1].lazy+=t[x].lazy)%=p;
(t[x*2+1].val+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1))%=p;
t[x].lazy=0;
}
}
void change(int x,int l,int r,int num)
{
if(t[x].l==l&&t[x].r==r)
{
(t[x].val+=num*(t[x].r-t[x].l+1))%=p;
(t[x].lazy+=num)%=p;
return;
}
downdata(x);
int mid=(t[x].l+t[x].r)>>1;
if(r<=mid) change(x*2,l,r,num);
else if(l>mid) change(x*2+1,l,r,num);
else change(x*2,l,mid,num),change(x*2+1,mid+1,r,num);
t[x].val=(t[x*2].val+t[x*2+1].val)%p;
}
int find(int x,int l,int r)
{
if(t[x].l==l&&t[x].r==r)
return t[x].val;
downdata(x);
int mid=(t[x].l+t[x].r)>>1;
if(r<=mid) return find(x*2,l,r);
else if(l>mid) return find(x*2+1,l,r);
else return (find(x*2,l,mid)+find(x*2+1,mid+1,r))%p;
}
}LT;
struct edge_node{
int to,next;
}a[N*2];
void addl(int x,int y)
{
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;
}
void dfs1(int x,int fa)
{
siz[x]=1;
for(int i=ls[x];i;i=a[i].next)
{
int y=a[i].to;
if(y==fa) continue;
dep[y]=dep[x]+1;
f[y]=x;
dfs1(y,x);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]])
son[x]=y;
}
}
void dfs2(int x,int fa)
{
seg[x]=++cnt;
id[cnt]=x;
if(son[x])
{
top[son[x]]=top[x];
dfs2(son[x],x);
}
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==fa||y==son[x]) continue;
top[y]=y;dfs2(y,x);
}
}
void path_change(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
LT.change(1,seg[top[x]],seg[x],z);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
LT.change(1,seg[x],seg[y],z);
return;
}
int path_ask(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
(ans+=LT.find(1,seg[top[x]],seg[x]))%=p;
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
(ans+=LT.find(1,seg[x],seg[y]))%=p;
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&p);
for(int i=1;i<=n;i++)
scanf("%d",&pw[i]);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
addl(x,y);addl(y,x);
}
dfs1(s,0);
top[s]=s;dfs2(s,0);
LT.build(1,1,n);
for(int i=1;i<=m;i++){
int t,x,y,z;
scanf("%d%d",&t,&x);
if(t==1){
scanf("%d%d",&y,&z);
path_change(x,y,z);
}
if(t==2){
scanf("%d",&y);
printf("%d\n",path_ask(x,y));
}
if(t==3){
scanf("%d",&z);
LT.change(1,seg[x],seg[x]+siz[x]-1,z);
}
if(t==4){
printf("%d\n",LT.find(1,seg[x],seg[x]+siz[x]-1));
}
}
}