http://codeforces.com/contest/1110/problem/F
这题本身不难,但是比赛的时候能不能做到这个题,能不能熟练地想到这些套路并且快速把它写出来就是个问题了
离线,把每个询问挂到对应的点上去
从根节点开始 d f s dfs dfs,每次经过一条边,就根据 d f s dfs dfs序确定影响到的区间,用线段树维护下最小值就行了
//线段树
#include
#define maxn 500010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define dinf 1e100
using namespace std;
typedef long long ll;
struct segtree
{
ll l, r, min, add;
segtree *lch, *rch;
}pool[maxn*4], *root;
ll N, head[maxn], to[maxn], nex[maxn], w[maxn], dist[maxn], etot, lb[maxn], rb[maxn], ndtot, ql[maxn], qr[maxn], Q, ans[maxn];
vector<ll> lis[maxn];
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
void adde(ll a, ll b, ll c)
{
to[++etot]=b;
w[etot]=c;
nex[etot]=head[a];
head[a]=etot;
}
ll dfs(ll pos)
{
ll i, p, mx=pos;
lb[pos]=pos;
for(p=head[pos];p;p=nex[p])
dist[to[p]]=dist[pos]+w[p], mx=max(mx,dfs(to[p]));
rb[pos]=mx;
return mx;
}
void pushdown(segtree *p)
{
p->min+=p->add;
if(p->lch)p->lch->add+=p->add, p->rch->add+=p->add;
p->add=0;
}
void pushup(segtree *p)
{
if(p->lch)pushdown(p->lch), pushdown(p->rch), p->min=min(p->lch->min,p->rch->min);
}
void build(segtree *p, ll l, ll r)
{
ll mid=l+r>>1;
p->l=l, p->r=r;
if(l==r)
{
p->min=head[l]?linf:dist[l];
return;
}
build(p->lch=pool+ ++ndtot,l,mid);
build(p->rch=pool+ ++ndtot,mid+1,r);
pushup(p);
}
ll segmin(segtree *p, ll l, ll r)
{
ll mid=p->l+p->r>>1, ans=linf;
pushdown(p);
if(l<=p->l and r>=p->r)return p->min;
if(l<=mid)ans=min(ans,segmin(p->lch,l,r));
if(r>mid)ans=min(ans,segmin(p->rch,l,r));
return ans;
}
void segadd(segtree *p, ll l, ll r, ll v)
{
ll mid=p->l+p->r>>1;
pushdown(p);
if(l<=p->l and r>=p->r){p->add+=v;return;}
if(l<=mid)segadd(p->lch,l,r,v);
if(r>mid)segadd(p->rch,l,r,v);
pushup(p);
}
void init()
{
ll i, p, w, v;
N=read(), Q=read();
for(i=2;i<=N;i++)
{
p=read(), w=read();
adde(p,i,w);
}
for(i=1;i<=Q;i++)
{
v=read(), ql[i]=read(), qr[i]=read();
lis[v].push_back(i);
}
dfs(1);
build(root=pool+ ++ndtot,1,N);
}
void solve(ll pos)
{
vector<ll>::iterator it;
ll p;
for(it=lis[pos].begin();it!=lis[pos].end();it++)
{
ans[*it]=segmin(root,ql[*it],qr[*it]);
}
for(p=head[pos];p;p=nex[p])
{
segadd(root,lb[to[p]],rb[to[p]],-w[p]);
if(lb[to[p]]>1)segadd(root,1,lb[to[p]]-1,w[p]);
if(rb[to[p]]<N)segadd(root,rb[to[p]]+1,N,w[p]);
solve(to[p]);
segadd(root,lb[to[p]],rb[to[p]],w[p]);
if(lb[to[p]]>1)segadd(root,1,lb[to[p]]-1,-w[p]);
if(rb[to[p]]<N)segadd(root,rb[to[p]]+1,N,-w[p]);
}
}
void print()
{
ll i;
for(i=1;i<=Q;i++)printf("%lld\n",ans[i]);
}
int main()
{
init();
solve(1);
print();
return 0;
}