[2016-05-25][树分治]

树分治不写就不熟啊,要多练习

/*hint:注意树分治中的vis和solve(G)并非solve(v)*/

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 200010
using namespace std;

int N, L, R;
const int inf = 0x7fffffff / 3;
struct Edge{int to, nxt, w, dis;}edge[maxn];
int h[maxn], cnt;
void add(int u, int v, int w){
	edge[++ cnt] = (Edge){v, h[u], w, 0}; h[u] = cnt;
	edge[++ cnt] = (Edge){u, h[v], w, 0}; h[v] = cnt;
}

namespace seg{
	int t[maxn << 2], v[maxn << 2], TMP;
	#define lc id << 1
	#define rc id << 1 | 1
	void init(){memset(t, 0, sizeof t);}
	void update(int id, int l, int r, int p, int val){
		if(l == r){//线段树底层写错了。 
			if(v[id] == TMP)t[id] = max(t[id], val);
			else v[id] = TMP, t[id] = val;
			return;
		}
		v[id] = TMP;
		int mid = l + r >> 1;
		if(p <= mid)update(lc, l, mid, p, val);
		else update(rc, mid + 1, r, p, val);
		t[id] = -inf;
		if(v[lc] == TMP)t[id] = max(t[id], t[lc]);
		if(v[rc] == TMP)t[id] = max(t[id], t[rc]);
	}
	
	int ask(int id, int l, int r, int L, int R){
		if(v[id] != TMP)return -inf;
		if(l == L && r == R)return t[id];
		int mid = l + r >> 1;
		if(R <= mid)return ask(lc, l, mid, L, R);
		if(L > mid) return ask(rc, mid+1, r, L, R);
		return max(ask(lc, l, mid, L, mid), ask(rc, mid + 1, r, mid + 1, R));
	}
}


int size[maxn], Sum, Mx, G;
bool vis[maxn];
int dp[maxn];
void getg(int u, int fa){
	size[u] = 1; dp[u] = 0;
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(vis[v] || v == fa)continue;
		getg(v, u);
		size[u] += size[v];
		dp[u] = max(dp[u], size[v]);
	}
	dp[u] = max(dp[u], Sum - size[u]);
	if(dp[u] < dp[G])G = u;
}

int d[maxn], vi[maxn], tim, mxdep;

void getdis(int u, int fa, int dis, int dep){
	if(dep > mxdep)mxdep = dep;
	if(vi[dep] != tim)vi[dep] = tim, d[dep] = dis; else d[dep] = max(d[dep], dis);
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa || vis[v])continue;
		getdis(v, u, dis + edge[i].dis, dep + 1);
	}
}

bool solve(int u){
	vis[u] = true;
	seg::TMP ++; 
	seg::update(1, 0, N, 0, 0);
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(vis[v])continue;
		tim ++; 
		mxdep = 0;
		getdis(v, u, edge[i].dis, 1);
		for(int j = 0; j <= mxdep; j ++){
			int A = L - j, B = R - j;
			if(A < 0)A = 0; if(B < 0)continue;
			if(seg::ask(1, 0, N, A, B) + d[j] >= 0)
				return true;
		}

		for(int j = 1; j <= mxdep; j ++)
			seg::update(1, 0, N, j, d[j]);
	}
	
	for(int i = h[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(vis[v])continue;
		Sum = size[v], G = 0, getg(v, u);
		if(solve(G))return true;
	}
	return false;
}

bool check(int mid){
	for(int i = 1; i <= cnt; i ++)
		if(edge[i].w >= mid)edge[i].dis = 1;
		else edge[i].dis = -1;
	for(int i = 1; i <= N; i ++)vis[i] = 0;
	seg::init();
	dp[0] = inf, Sum = N, G = 0, getg(1, 0);
	return solve(G);
}

int main(){
	scanf("%d%d%d", &N, &L, &R);
	static int hs[maxn], c = 0;
	int u, v, w, mn = inf, mx = -inf; 
	for(int i = 1; i < N; i ++){
		scanf("%d%d%d", &u, &v, &w);
		add(u, v, w);
		mx = max(mx, w);
		mn = min(mn, w);
		hs[++ c] = w; 
	}

	sort(hs + 1, hs + 1 + c);
	c = unique(hs + 1, hs + 1 + c) - hs - 1;
	

	int l = 1, r = c;
	while(l < r){
		int mid = l + (r - l + 1) / 2;
		if(check(hs[mid]))l = mid;
		else r = mid - 1;
	}

	printf("%d\n", hs[l]);
	return 0;
}

  

posted @ 2016-05-25 15:59  _Horizon  阅读(106)  评论(0)    收藏  举报