P7011-[CERC2013]Escape [heap, heuristic merge]

Keywords: data structure Luogu

Topic

Title Link: https://www.luogu.com.cn/problem/P7011

General idea of the topic

give n n A tree with n points starts from one and goes to t t t. The initial weight value is 0 0 0, each node has a weight w i w_i wi, when walking through this node for the first time, the weight will be added to the weight of this node. It is required that the weight of the whole process can not be negative, so as to find out whether it can be reached t t t.

1 ≤ n ≤ 2 × 1 0 5 1\leq n\leq 2\times 10^5 1≤n≤2×105

Problem solving ideas

The first troublesome point is that there is a limit on the end point. After we reach the end point, we don't need to consider other points. We might as well follow the end point with a weight of + ∞ +\infty +∞, and then the problem becomes whether to traverse the whole tree.

Next, we will find that there is a very troublesome point, because we may enter a subtree many times. A more violent idea is that we can set f x , j f_{x,j} fx,j , means that we have a weight of j j Enter when j x x The maximum weight that the subtree of x can become when it comes out again.

Suppose we start from j j j increased to j + k j+k j+k, then the contribution you can get is f i , j + k − f i , j f_{i,j+k}-f_{i,j} fi,j+k − fi,j, it is not difficult to find that for a f i , j f_{i,j} fi,j # the number of different weights only has the maximum subtree size. Consider maintaining the positions of these transformations as several binary units ( x , y ) (x,y) (x,y) indicates that the weight is x x x can be obtained when entering y y The weight of y, obviously we have these intervals [ x , x + y ] [x,x+y] [x,x+y] are disjoint (because if they intersect, more weights can be obtained at one time).

When merging, we directly merge these intervals (because even if they intersect, we can merge these intervals later when considering the node weight), and then according to the node weight x x The weight of x merges the previous interval.

As for the merging of two heaps, it is natural to use the merging heap, but it is not as easy to write as the heuristic merging.

Time complexity: O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n)

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define mp(x,y) make_pair(x,y)
using namespace std;
const ll N=2e5+10;
struct node{
	ll to,next;
}a[N<<1];
ll T,n,t,tot,ls[N],p[N],w[N];
priority_queue<pair<ll,ll> >q[N];
void addl(ll x,ll y){
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;return;
}
void dfs(ll x,ll fa){
	p[x]=x;
	for(ll i=ls[x];i;i=a[i].next){
		ll y=a[i].to;
		if(y==fa)continue;dfs(y,x);
		if(q[p[y]].size()>q[p[x]].size())
			swap(p[x],p[y]);
		while(!q[p[y]].empty()){
			q[p[x]].push(q[p[y]].top());
			q[p[y]].pop();
		}
	}
	pair<ll,ll> k=mp(0,w[x]);
	while(!q[p[x]].empty()){
		pair<ll,ll> z=q[p[x]].top();z.first=-z.first;
		if(k.second>=0&&z.first>k.first+k.second)break;
		k=mp(max(k.first,z.first-k.second),k.second+z.second);
		q[p[x]].pop();
	}
	k.first=-k.first;
	if(k.second>0)q[p[x]].push(k);
	return;
}
signed main()
{
	scanf("%lld",&T);
	while(T--){
		scanf("%lld%lld",&n,&t);tot=0;
		for(ll i=1;i<=n+1;i++){
			ls[i]=0;
			while(!q[i].empty())q[i].pop();
		}
		for(ll i=1;i<=n;i++)scanf("%lld",&w[i]);
		for(ll i=1,x,y;i<n;i++){
			scanf("%lld%lld",&x,&y);
			addl(x,y);addl(y,x);
		}
		++n;w[n]=1e18;
		addl(t,n);addl(n,t);
		dfs(1,0);
		if(q[p[1]].empty())puts("trapped");
		else{
			pair<ll,ll> w=q[p[1]].top();
			if(w.first>=0&&w.second>1e17)
				puts("escaped");
			else puts("trapped");
		}
	}
	return 0;
}

Posted by nosmasu on Tue, 16 Nov 2021 03:55:50 -0800