常规:
struct slpf
{
const int nn;
struct node
{
int l, r, tag;
int val;
};
vector<node> tr;
vector<int> fa, dep, son, siz, top, dfn, w;
vector<int> v;
vector<vector<int>> g;
int tim;
slpf(int n1) : nn(n1), tr((n1 + 10) << 2), fa(n1 + 1), dep(n1 + 1), son(n1 + 1, 0), siz(n1 + 1), top(n1 + 1), dfn(n1 + 1), w(n1 + 1), v(n1 + 1), g(n1 + 1), tim(0) {}
void add(int uu, int vv)
{
g[uu].push_back(vv);
}
void dfs1(int now, int fr)
{
fa[now] = fr;
dep[now] = dep[fr] + 1;
siz[now] = 1;
int max_size = -1;
for (int x : g[now])
{
if (x == fr)
continue;
dfs1(x, now);
siz[now] += siz[x];
if (siz[x] > max_size)
{
max_size = siz[x];
son[now] = x;
}
}
}
void dfs2(int now, int tp)
{
dfn[now] = ++tim;
top[now] = tp;
w[tim] = v[now];
if (!son[now])
return;
dfs2(son[now], tp);
for (int x : g[now])
{
if (x == fa[now] || x == son[now])
continue;
dfs2(x, x);
}
}
void build(int root, int l, int r) //根节点为1,范围从1-n
{
tr[root].l = l;
tr[root].r = r;
tr[root].tag = 0; // add的初始值为0
if (l == r)
{
tr[root].val = w[l]; //初始值
return;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
void spread(int p)
{
if (tr[p].tag != 0)
{
tr[p << 1].val += tr[p].tag * (tr[p << 1].r - tr[p << 1].l + 1);
tr[p << 1 | 1].val += tr[p].tag * (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1);
tr[p << 1].tag += tr[p].tag;
tr[p << 1 | 1].tag += tr[p].tag;
tr[p].tag = 0;
}
}
void update(int root, int l, int r, int x)
{
if (l <= tr[root].l && r >= tr[root].r)
{
tr[root].val += x * (tr[root].r - tr[root].l + 1);
tr[root].tag += x;
return;
}
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
if (l <= mid)
update(root << 1, l, r, x);
if (r > mid)
update(root << 1 | 1, l, r, x);
tr[root].val = tr[root << 1].val + tr[root << 1 | 1].val;
}
int getsum(int root, int l, int r)
{
if (l <= tr[root].l && r >= tr[root].r)
return tr[root].val;
spread(root);
int mid = (tr[root].l + tr[root].r) >> 1;
int ans = 0;
if (l <= mid)
ans = (ans + getsum(root << 1, l, r));
if (r > mid)
ans = (ans + getsum(root << 1 | 1, l, r));
return ans;
}
void make_tree(int root, vector<int> &arr)
{
v = arr;
dfs1(root, root);
dfs2(root, root);
build(1, 1, nn);
}
void update_son(int x, int z) // x为根结点的子树所有节点值+z
{
update(1, dfn[x], dfn[x] + siz[x] - 1, z);
}
int query_son(int x) // x为根结点的子树所有节点值之和
{
return getsum(1, dfn[x], dfn[x] + siz[x] - 1);
}
void update_chain(int x, int y, int z)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
update(1, dfn[top[x]], dfn[x], z);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
update(1, dfn[x], dfn[y], z);
}
int query_chain(int x, int y)
{
int res = 0;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]])
swap(x, y);
res += getsum(1, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
res += getsum(1, dfn[x], dfn[y]);
return res;
}
void remake_tree(int root)
{
fa.assign(nn + 1, 0);
dep.assign(nn + 1, 0);
son.assign(nn + 1, 0);
siz.assign(nn + 1, 0);
top.assign(nn + 1, 0);
dfn.assign(nn + 1, 0);
tim = 0;
dfs1(root, root);
dfs2(root, root);
build(1, 1, nn);
}
int lca(int x, int y)
{
while (top[x] != top[y])
{
if (dep[top[x]] >= dep[top[y]])
x = fa[top[x]];
else
y = fa[top[y]];
}
return dep[x] < dep[y] ? x : y;
}
};
带取模:
struct slpf{
const int nn;
struct node{
int l,r,tag;
int val;
};
vector<node> tr;
vector<int> fa,dep,son,siz,top,dfn,w;
vector<int> v;
vector<vector<int>> g;
int tim;
slpf(int n1):nn(n1),tr((n1+10)*4),fa(n1+1),dep(n1+1),son(n1+1,0),siz(n1+1),top(n1+1),dfn(n1+1),w(n1+1),v(n1+1),g(n1+1),tim(0){}
void add(int uu,int vv)
{
g[uu].push_back(vv);
}
void dfs1(int now,int fr)
{
fa[now]=fr;
dep[now]=dep[fr]+1;
siz[now]=1;
int max_size=-1;
for(int x:g[now])
{
if(x==fr)
continue;
dfs1(x,now);
siz[now]+=siz[x];
if(siz[x]>max_size)
{
max_size=siz[x];
son[now]=x;
}
}
}
void dfs2(int now,int tp)
{
dfn[now]=++tim;
top[now]=tp;
w[tim]=v[now];
if(!son[now])
return;
dfs2(son[now],tp);
for(int x:g[now])
{
if(x==fa[now]||x==son[now])
continue;
dfs2(x,x);
}
}
void build(int root,int l,int r)//根节点为1,范围从1-n
{
tr[root].l=l;
tr[root].r=r;
tr[root].tag=0;//add的初始值为0
if(l==r)
{
tr[root].val=w[l];//初始值
return;
}
int mid=(l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
tr[root].val=tr[root*2].val+tr[root*2+1].val;
}
void spread(int p)
{
if(tr[p].tag!=0)
{
tr[p*2].val+=tr[p].tag*(tr[p*2].r-tr[p*2].l+1);
tr[p*2+1].val+=tr[p].tag*(tr[p*2+1].r-tr[p*2+1].l+1);
tr[p*2].tag+=tr[p].tag;
tr[p*2+1].tag+=tr[p].tag;
tr[p].tag=0;
}
}
void update(int root,int l,int r,int x)
{
if(l<=tr[root].l&&r>=tr[root].r)
{
tr[root].val+=x*(tr[root].r-tr[root].l+1);
tr[root].tag+=x;
return;
}
spread(root);
int mid=(tr[root].l+tr[root].r)>>1;
if(l<=mid)
update(root*2,l,r,x);
if(r>mid)
update(root*2+1,l,r,x);
tr[root].val=tr[root*2].val+tr[root*2+1].val;
}
int getsum(int root,int l,int r)
{
if(l<=tr[root].l&&r>=tr[root].r)
return tr[root].val;
spread(root);
int mid=(tr[root].l+tr[root].r)>>1;
int ans=0;
if(l<=mid)
ans=(ans+getsum(root*2,l,r));
if(r>mid)
ans=(ans+getsum(root*2+1,l,r));
return ans;
}
void make_tree(int root,vector<int> &arr)
{
v=arr;
dfs1(root,root);
dfs2(root,root);
build(1,1,nn);
}
void remake_tree(int root)
{
fa.assign(nn+1,0);
dep.assign(nn+1,0);
son.assign(nn+1,0);
siz.assign(nn+1,0);
top.assign(nn+1,0);
dfn.assign(nn+1,0);
tim=0;
dfs1(root,root);
dfs2(root,root);
build(1,1,nn);
}
void update_son(int x,int z)//x为根结点的子树所有节点值+z
{
update(1,dfn[x],dfn[x]+siz[x]-1,z);
}
int query_son(int x)//x为根结点的子树所有节点值之和
{
return getsum(1,dfn[x],dfn[x]+siz[x]-1);
}
void update_chain(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
update(1,dfn[top[x]],dfn[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
update(1,dfn[x],dfn[y],z);
}
int query_chain(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
swap(x,y);
res+=getsum(1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y])
swap(x,y);
res+=getsum(1,dfn[x],dfn[y]);
return res;
}
};