codeforces1110F Nearest Leaf

題面

題意

給出一棵樹,它的節點的標號恰好爲其dfs序,多次詢問,每次詢問給出三個數u,l,r,求點u到標號在[l,r][l,r]中的葉子節點的最近距離。

做法

考慮用線段樹維護點1到各個葉子節點的距離,發現若要維護點1的兒子節點點2到各個葉子節點的距離,只要將點2的子樹中的所有葉子節點的距離減去邊權,其餘葉子節點加上邊權,這樣只要將詢問離線,再維護區間加和區間最小值即可。

代碼

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N 500100
using namespace std;

ll n,Q,cl,tt,qq,lea[N],id[N],deep[N],in[N],out[N],ans[N];
bool il[N];
struct Node
{
	ll ls,rs,mn,sum;
}node[N<<1];
struct Que
{
	ll pos,l,r,id;
	bool operator < (const Que &u) const
	{
		return pos<u.pos;
	}
}que[N];
vector<ll>to[N],quan[N];

inline void ad(ll u,ll v,ll w)
{
	to[u].push_back(v);
	quan[u].push_back(w);
}

inline void up(ll now)
{
	ll L=node[now].ls,R=node[now].rs;
	node[now].mn=min(node[L].mn,node[R].mn)+node[now].sum;
}

void build(ll now,ll l,ll r)
{
	if(l==r)
	{
		node[now].mn=deep[lea[l]];
		return;
	}
	ll mid=((l+r)>>1);
	node[now].ls=++tt;
	build(tt,l,mid);
	node[now].rs=++tt;
	build(tt,mid+1,r);
	up(now);
}

void add(ll now,ll l,ll r,ll u,ll v,ll w)
{
	if(u<=l&&r<=v)
	{
		node[now].sum+=w;
		node[now].mn+=w;
		return;
	}
	ll mid=((l+r)>>1);
	if(u<=mid) add(node[now].ls,l,mid,u,v,w);
	if(v>mid) add(node[now].rs,mid+1,r,u,v,w);
	up(now);
}

ll ask(ll now,ll l,ll r,ll u,ll v)
{
	if(u<=l&&r<=v) return node[now].mn;
	ll res=INF,mid=((l+r)>>1);
	if(u<=mid) res=min(res,ask(node[now].ls,l,mid,u,v));
	if(mid<v) res=min(res,ask(node[now].rs,mid+1,r,u,v));
	return res+node[now].sum;
}

void dfs(ll now,ll last)
{
	ll i,q;
	bool flag=0;
	in[now]=cl+1;
	for(i=0;i<to[now].size();i++)
	{
		q=to[now][i];
		if(q==last) continue;
		flag=1;
		deep[q]=deep[now]+quan[now][i];
		dfs(q,now);
	}
	if(!flag) lea[++cl]=now,id[now]=cl,il[now]=1;
	out[now]=cl;
}

void Dfs(ll now,ll last)
{
	ll i,q;
	for(;qq<=Q&&que[qq].pos==now;qq++)
	{
		ans[que[qq].id]=ask(1,1,cl,in[que[qq].l],in[que[qq].r]-(!il[que[qq].r]));
	}
	for(i=0;i<to[now].size();i++)
	{
		q=to[now][i];
		if(q==last) continue;
		add(1,1,cl,in[q],out[q],-quan[now][i]);
		if(in[q]>1) add(1,1,cl,1,in[q]-1,quan[now][i]);//cerr<<1<<' '<<in[q]-1<<"+"<<endl;
		if(out[q]<cl) add(1,1,cl,out[q]+1,cl,quan[now][i]);//cerr<<out[q]+1<<" "<<cl<<"+"<<endl;
		Dfs(q,now);
		add(1,1,cl,in[q],out[q],quan[now][i]);
		if(in[q]>1) add(1,1,cl,1,in[q]-1,-quan[now][i]);
		if(out[q]<cl) add(1,1,cl,out[q]+1,cl,-quan[now][i]);
	}
}

int main()
{
	ll i,j,p,q;
	cin>>n>>Q;
	for(i=2;i<=n;i++)
	{
		scanf("%lld%lld",&p,&q);
		ad(i,p,q),ad(p,i,q);
	}
	for(i=1;i<=Q;i++)
	{
		scanf("%lld%lld%lld",&que[i].pos,&que[i].l,&que[i].r);
		que[i].id=i;
	}
	sort(que+1,que+Q+1);
	dfs(1,-1);
	build(tt=1,1,cl);
	qq=1;
	Dfs(1,-1);
	for(i=1;i<=Q;i++) printf("%lld\n",ans[i]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章