https://www.luogu.com.cn/problem/P3178
1为根,查询树上路径,单点修改和子树修改
数据范围: n ≤ 1 0 5 n\leq 10^5 n≤105
默个板子
时间复杂度: O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)
#include
#include
#include
#define N 100010
#define LL long long
using namespace std;int n,m,tot,l[N],fa[N],dep[N],siz[N],son[N],top[N],id[N],cnt,nv[N],x,y,opt;
struct node{int next,to;}e[N*2];
inline void add(int u,int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
LL v[N],z;
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void dfs1(int x)
{
siz[x]=1;
int maxn=-1;
for(register int i=l[x];i;i=e[i].next)
{
int y=e[i].to;
if(y==fa[x]) continue;
fa[y]=x;dep[y]=dep[x]+1;
dfs1(y);
siz[x]+=siz[y];
if(siz[y]>maxn)
{
maxn=siz[y];
son[x]=y;
}
}
return;
}
inline void dfs2(int x,int topf)
{
top[x]=topf;
id[x]=++cnt;
nv[cnt]=v[x];
if(son[x]==0) return;
if(son[x]) dfs2(son[x],topf);
for(register int i=l[x];i;i=e[i].next)
{
int y=e[i].to;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
return;
}
struct xds
{
#define lson k<<1
#define rson k<<1|1
LL sum[N<<2],lzy[N<<2];
inline void build(int k=1,int l=1,int r=cnt)
{
if(l==r)
{
sum[k]=nv[l];
return;
}
int mid=l+r>>1;
build(lson,l,mid);build(rson,mid+1,r);
sum[k]=sum[lson]+sum[rson];
return;
}
inline void pushdown(int k,int l,int r)
{
if(lzy[k]==0) return;
int mid=l+r>>1;
lzy[lson]+=lzy[k];lzy[rson]+=lzy[k];
sum[lson]+=lzy[k]*(mid-l+1);
sum[rson]+=lzy[k]*(r-mid);
lzy[k]=0;
return;
}
inline void Modify(int ql,int qr,LL v,int k=1,int l=1,int r=cnt)
{
if(ql<=l&&r<=qr) {lzy[k]+=v;sum[k]+=(r-l+1)*v;return;}
pushdown(k,l,r);
int mid=l+r>>1;
if(ql<=mid) Modify(ql,qr,v,lson,l,mid);
if(qr>mid) Modify(ql,qr,v,rson,mid+1,r);
sum[k]=sum[lson]+sum[rson];
return;
}
inline LL Query(int ql,int qr,int k=1,int l=1,int r=cnt)
{
if(ql<=l&&r<=qr) return sum[k];
pushdown(k,l,r);
int mid=l+r>>1;LL res=0;
if(ql<=mid) res+=Query(ql,qr,lson,l,mid);
if(qr>mid) res+=Query(ql,qr,rson,mid+1,r);
sum[k]=sum[lson]+sum[rson];
return res;
}
}T;
inline void gzs(int x,LL v){T.Modify(id[x],id[x]+siz[x]-1,v);return;}
inline void gdd(int x,LL v){T.Modify(id[x],id[x],v);return;}
inline LL gas(int x,int y)
{
LL res=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res+=T.Query(id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res+=T.Query(id[x],id[y]);
return res;
}
signed main()
{
n=read();m=read();dep[1]=1;
for(register int i=1;i<=n;i++) v[i]=read();
for(register int i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
dfs1(1);
dfs2(1,1);
T.build();
while(m--)
{
opt=read();
if(opt==1)
{
x=read();z=read();
gdd(x,z);
}
if(opt==2)
{
x=read();z=read();
gzs(x,z);
}
if(opt==3)
{
x=read();
printf("%lld\n",gas(x,1));
}
}
}