[CF1110F]CF1110F Nearest Leaf
Description:
给定一棵以1 为根的n个节点有根树
1不是叶子
给定m次询问
形如 v l r
输出以v为起点 终点编号为l - r以内的叶子中 v到叶子最近的距离
注意:如果我们 DFS 这棵树,对于每个点都递增枚举儿子节点,每访问到一个节点就记录其编号,那么得到的序列刚好为 1 到 n。
Hint:
\(n,m \le 5*10^5\)
Solution:
考虑每次走一条边,子树叶子最小值会\(+w_i\),其他叶子会\(-w_i\) (这里没想到)
这样我们可以把询问离线,先把非叶子节点赋为inf
每次在线段树上区间加,区间求min就行了
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=5e5+5;
const ll inf=1e18;
ll n,m,cnt,in[mxn],hd[mxn],sz[mxn];
ll tr[mxn<<2],tag[mxn<<2],dep[mxn],ans[mxn];
struct Q {
ll l,r,id;
};
vector<Q> q[mxn];
inline ll read() {
char c=getchar(); ll x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}
struct ed {
ll to,nxt; ll w;
}t[mxn<<1];
void push_down(ll p,ll l,ll r) {
if(tag[p]) {
ll mid=(l+r)>>1;
tag[ls]+=tag[p]; tag[rs]+=tag[p];
tr[ls]+=tag[p];
tr[rs]+=tag[p];
tag[p]=0;
}
}
inline void add(ll u,ll v,ll w) {
t[++cnt]=(ed) {v,hd[u],w}; hd[u]=cnt;
}
void update(ll l,ll r,ll ql,ll qr,ll val,ll p) {
if(ql<=l&&r<=qr) {
tag[p]+=val;
tr[p]+=val;
return ;
}
ll mid=(l+r)>>1; push_down(p,l,r);
if(ql<=mid) update(l,mid,ql,qr,val,ls);
if(qr>mid) update(mid+1,r,ql,qr,val,rs);
tr[p]=min(tr[ls],tr[rs]);
}
ll query(ll l,ll r,ll ql,ll qr,ll p) {
if(ql<=l&&r<=qr) return tr[p];
ll mid=(l+r)>>1; ll res=inf; push_down(p,l,r);
if(ql<=mid) chkmin(res,query(l,mid,ql,qr,ls));
if(qr>mid) chkmin(res,query(mid+1,r,ql,qr,rs));
return res;
}
void mod(ll l,ll r,ll pos,ll val,ll p) {
if(l==r) {
tr[p]=val;
return ;
}
ll mid=(l+r)>>1;
if(pos<=mid) mod(l,mid,pos,val,ls);
else mod(mid+1,r,pos,val,rs);
tr[p]=min(tr[ls],tr[rs]);
}
void build(ll l,ll r,ll p) {
if(l==r) {
tr[p]=inf;
return ;
}
ll mid=(l+r)>>1;
build(l,mid,ls);
build(mid+1,r,rs);
tr[p]=min(tr[ls],tr[rs]);
}
void dfs(ll u,ll fa) {
sz[u]=1;
if(in[u]==1) mod(1,n,u,dep[u],1);
for(ll i=hd[u];i;i=t[i].nxt) {
ll v=t[i].to;
if(v==fa) continue ;
dep[v]=dep[u]+t[i].w;
dfs(v,u); sz[u]+=sz[v];
}
}
void solve(ll u,ll fa) {
for(ll i=0;i<q[u].size();++i) {
Q tp=q[u][i];
ans[tp.id]=query(1,n,tp.l,tp.r,1);
}
for(ll i=hd[u];i;i=t[i].nxt) {
ll v=t[i].to;
if(v==fa) continue ;
update(1,n,1,n,t[i].w,1);
update(1,n,v,v+sz[v]-1,-2*t[i].w,1);
solve(v,u);
update(1,n,1,n,-t[i].w,1);
update(1,n,v,v+sz[v]-1,2*t[i].w,1);
}
}
int main()
{
n=read(); m=read(); ll u,pos,l,r; ll w; build(1,n,1);
for(ll i=2;i<=n;++i) {
u=read(); w=read();
add(u,i,w); add(i,u,w); ++in[u],++in[i];
}
for(ll i=1;i<=m;++i)
pos=read(),l=read(),r=read(),q[pos].push_back((Q){l,r,i});
dfs(1,0); solve(1,0);
for(ll i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}