题目来源
P3384 【模板】树链剖分
https://www.luogu.org/problemnew/show/3384
代码(C++)
#include <cstdio>
#include <bitset>
#define ll long long
#define N 100010
#define M 200010
using namespace std;
struct tree{ll x,y,sum,lazy;tree *l,*r;};
tree *root,*null=new tree();
ll n,m,s,p,u,v,w,x,y,z,cnt=0,t[N],wei[N];
bitset<N> g; ll c,ma[N],nt[N];
ll he[N],en[M],ne[M],si[N],hs[N],fa[N],de[N];
inline void add();
inline ll read();
tree *build(ll st,ll en);
void dfs2(ll pos,ll top);
void dfs1(ll pos,ll depth);
ll ask(ll st,ll en,tree *pos);
inline ll lca2(ll x,ll y);
inline void lca1(ll x,ll y,ll num);
void change(ll st,ll en,tree *pos,ll num);
int main()
{
n=read(); m=read(); s=read(); p=read();
for(ll i=1;i<=n;++i)
wei[i]=read();
for(ll i=1;i<n;++i)
u=read(),v=read(),add();
dfs1(s,1); g=0; cnt=0; dfs2(s,s);
root=build(1,n);
for(ll i=1;i<=m;++i)
{
c=read();
switch(c)
{
case 1:
x=read(); y=read(); z=read();
lca1(x,y,z);
break;
case 2:
x=read(); y=read();
printf("%lld\n",lca2(x,y));
break;
case 3:
x=read(); y=read();
change(ma[x],ma[x]+si[x]-1,root,y);
break;
case 4:
x=read();
printf("%lld\n",ask(ma[x],ma[x]+si[x]-1,root)%p);
break;
}
}
return 0;
}
inline ll lca2(ll x,ll y)
{
ll res=0;
while(t[x]!=t[y])
{
if(de[t[x]]<de[t[y]]){ll z=x; x=y; y=z;}
res+=ask(ma[t[x]],ma[x],root); res%=p;
x=fa[t[x]];
}
if(de[x]>de[y]){ll z=x; x=y; y=z;}
res+=ask(ma[x],ma[y],root);
return res%p;
}
inline void lca1(ll x,ll y,ll num)
{
while(t[x]!=t[y])
{
if(de[t[x]]<de[t[y]]){ll z=x; x=y; y=z;}
change(ma[t[x]],ma[x],root,num);
x=fa[t[x]];
}
if(de[x]>de[y]){ll z=x; x=y; y=z;}
change(ma[x],ma[y],root,num);
return ;
}
void change(ll st,ll en,tree *pos,ll num)
{
if(pos->lazy&&pos->l!=null)
{
pos->l->sum+=(pos->l->y-pos->l->x+1)*pos->lazy;
pos->r->sum+=(pos->r->y-pos->r->x+1)*pos->lazy;
pos->l->lazy+=pos->lazy;
pos->r->lazy+=pos->lazy;
pos->lazy=0;
}
pos->sum+=(en-st+1)*num;
if(pos->x==st&&pos->y==en)
{
pos->lazy+=num;
return ;
}
if(en<=pos->l->y)
change(st,en,pos->l,num);
else if(st>=pos->r->x)
change(st,en,pos->r,num);
else
change(st,pos->l->y,pos->l,num),
change(pos->r->x,en,pos->r,num);
return ;
}
ll ask(ll st,ll en,tree *pos)
{
if(pos->lazy&&pos->l!=null)
{
pos->l->sum+=(pos->l->y-pos->l->x+1)*pos->lazy;
pos->r->sum+=(pos->r->y-pos->r->x+1)*pos->lazy;
pos->l->lazy+=pos->lazy;
pos->r->lazy+=pos->lazy;
pos->lazy=0;
}
if(pos->x==st&&pos->y==en)
return pos->sum%p;
if(en<=pos->l->y)
return ask(st,en,pos->l);
if(st>=pos->r->x)
return ask(st,en,pos->r);
ll res=0;
res+=ask(st,pos->l->y,pos->l);
res+=ask(pos->r->x,en,pos->r);
return res%p;
}
tree *build(ll st,ll en)
{
tree *k=new tree();
k->x=st; k->y=en; k->lazy=0;
if(st==en)
k->l=null,k->r=null,k->sum=wei[nt[st]];
else
k->l=build(st,(st+en)/2),
k->r=build((st+en)/2+1,en),
k->sum=k->l->sum+k->r->sum;
return k;
}
void dfs2(ll pos,ll top)
{
g[pos]=1; t[pos]=top;
++cnt; ma[pos]=cnt; nt[cnt]=pos;
if(hs[pos])
dfs2(hs[pos],top);
for(ll k=he[pos];k;k=ne[k])
if(!g[en[k]])
dfs2(en[k],en[k]);
return ;
}
void dfs1(ll pos,ll depth)
{
g[pos]=1; si[pos]=1; de[pos]=depth;
for(ll k=he[pos];k;k=ne[k])
if(!g[en[k]])
{
dfs1(en[k],depth+1);
fa[en[k]]=pos;
si[pos]+=si[en[k]];
if(si[en[k]]>si[hs[pos]])
hs[pos]=en[k];
}
return ;
}
inline void add()
{
en[++cnt]=v; ne[cnt]=he[u]; he[u]=cnt;
en[++cnt]=u; ne[cnt]=he[v]; he[v]=cnt;
}
inline ll read()
{
char x=getchar(); ll num=0;
while(!(x>=48&&x<=57))
x=getchar();
while(x>=48&&x<=57)
num=num*10+x-48,x=getchar();
return num;
}