题解 幸福的道路

题意:给定一棵树,将树上每个点的最远距离组成的序列记为{an},在{an}上选出一段连续区间[l,r],用e表示{al…r}的极差,满足e<=M,求出r-l+1的最大值。
首先注意这道题是连续的,我就被坑了
首先可以知道要求离每个点的最远距离,可以暴力;
考虑优化,换根dp;
首先维护四个数组
\(f[u],fc[u],g[u],gc[u]\)
f分别表示以u为根的子树,u的最远距离;
和不重复的经过另一条边的最远距离;
g表示以u为起点,u的最远距离;
和不重复的经过另一条边的最远距离;
首先暴力算出以一为根的最远距离
然后换根,看代码
忘了,最后要求的是连续区间最大差值不超过m的;
可以同时用最大最小单调队列二维护;

#include <bits/stdc++.h>

using namespace std;

inline long long read() {
	long long s = 0, f = 1; char ch;
	while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
	for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
	return s * f;
}

const int N = 1e6 + 5;
int n, m, cnt, ans;
int head[N];
long long f[N], fc[N], g[N], gc[N], q1[N], q2[N];
struct edge {
	int nxt, to, val;
} e[N << 1];

void add(int x, int y, int z) {
	e[++cnt].nxt = head[x]; head[x] = cnt; e[cnt].to = y; e[cnt].val = z;
}

void dfs(int x, int fa) {
	for(int i = head[x]; i ; i = e[i].nxt) {
		int y = e[i].to; if(y == fa) continue;
		dfs(y, x);
	}
 	for(int i = head[x]; i ; i = e[i].nxt) {
		int y = e[i].to; if(y == fa) continue;
		if(f[x] < f[y] + e[i].val) {
			fc[x] = f[x];
			f[x] = max(f[x], f[y] + e[i].val);
		}
		else
			if(fc[x] < f[y] + e[i].val) {
				fc[x] = max(fc[x], f[y] + e[i].val);
			}
	}
}

void dfs2(int x, int fa, int w) {
	if(x == 1) {
		g[1] = f[1]; gc[1] = fc[1];
		for(int i = head[x]; i ; i = e[i].nxt) {
			int y = e[i].to; if(y == fa) continue;
			else dfs2(y, x, e[i].val);
		}
	}
	else {
		if(f[x] + w != g[fa]) {
			if(f[x] < w + g[fa]) {
				g[x] = w + g[fa];
				gc[x] = f[x];
			}
			else {
				g[x] = f[x];
				gc[x] = max(fc[x], w + g[fa]);
			}
		}
		else {
			if(f[x] < w + gc[fa]) {
				g[x] = w + gc[fa];
				gc[x] = f[x];
			}
			else {
				g[x] = f[x];
				gc[x] = max(fc[x], w + gc[fa]);
			}
		}
		for(int i = head[x]; i ; i = e[i].nxt) {
			int y = e[i].to; if(y == fa) continue;
			else dfs2(y, x, e[i].val);
		}
	}
}

int main() {
	
//	freopen("t3.in","r",stdin); freopen("t3.out","w",stdout);
	
	n = read(); m = read();
	for(int i = 2, x, y;i <= n; i++) {
		x = read(); y = read();
		add(i, x, y); add(x, i, y);
	}
	
	dfs(1, 0);
	dfs2(1, 0, 0);
	int l1 = 1, r1 = 0, l2 = 1, r2 = 0, t = 1;
	// for(int i=1;i<=n;i++) cout<<g[i]<<"\n";
	for(int i = 1;i <= n; i++)
	{
		while(l1 <= r1 && g[q1[r1]] <= g[i]) r1--;
		q1[++r1] = i;
		while(l2 <= r2 && g[q2[r2]] >= g[i]) r2--;
		q2[++r2] = i;
		while(g[q1[l1]] - g[q2[l2]] > m)
			if(q1[l1] < q2[l2]) t = q1[l1] + 1, l1++;
			else t = q2[l2] + 1, l2++;
		ans = max(ans, i - t + 1);
	}
	printf("%d\n", ans);
//	cout << endl;
//	for(int i = 1;i <= n; i++) cout << i << ' ' << f[i] << " " << fc[i] << endl;
//	cout << endl;
//	for(int i = 1;i <= n; i++) cout << i << ' ' << g[i] << endl;
	
	fclose(stdin); fclose(stdout);
	return 0;
}

/*
3 2
1 1
1 3
*/
posted @ 2020-09-12 21:34  Aswert  阅读(172)  评论(0编辑  收藏  举报