幸福的道路 【直径+振幅区间】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/81988482

问题 K(2415): 幸福的道路

时间限制: 3 Sec  内存限制: 128 MB

题目描述

小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.

他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.

他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).

他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?

输入

第一行包含两个整数N,M(M≤109). 
第二至第N行,每行两个数字Fi ,Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.

输出

最长的连续锻炼天数

样例输入

Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

3 2
1 1
1 3

样例输出

3

提示

50%的数据N≤1000 

80%的数据N≤100000 

100%的数据N≤1000000

分析:

       首先,求出树中每个点到树中最远点的距离,存于 f 数组中

       定义树的直径为树中最长链,则 f[i] = max(dis(i,直径的一端点),dis(i,直径的另一端点))

证明:    显然,距离u点最远的点,即从u开始dfs找到的最远点

             设点v是u的最远点

        (1)  若u在直径上,则v必为直径一端点,若不是,设直径端点为w,则dis[u][v]>dis[u][w],直径可以更长,矛盾

         (2) 若u不在直径上,则u到v必与直径相交,反证如下图:

        求出f[i]后,就是在f数组中求振幅(max-min)小于等于m的最大长度

       用L,R在1~n移动,同时用单调栈维护最大和最小值,不满足则L++,同时弹出栈中在L之前的值

#include<cstdio>
#include<cctype>
#include<algorithm>
#define maxn 1000005
using namespace std;
int n,m,ans;
int fir[maxn],nxt[2*maxn],to[2*maxn],w[2*maxn],tot;
long long f[maxn];
int S1[maxn],S2[maxn],h1,h2,t1=-1,t2=-1;
inline void get(int &a)
{
	char c;a=0;
	while(!isdigit(c=getchar()));
	while(isdigit(c)) a=a*10+c-'0',c=getchar();
}
inline void line(int x,int y,int z)
{
	nxt[++tot]=fir[x];
	fir[x]=tot;
	to[tot]=y;
	w[tot]=z;
}
inline void dfs(int u,int past,long long s,int &id)
{
	if(s>f[id]) id=u;
	if(s>f[u]) f[u]=s;
	for(int i=fir[u];i;i=nxt[i])
		if(to[i]!=past) dfs(to[i],u,s+w[i],id);
}
int main()
{
	int x,y,L;
	get(n),get(m);
	for(int i=2;i<=n;i++)
		get(x),get(y),line(i,x,y),line(x,i,y);
	x=y=0,dfs(1,0,0,x);
	dfs(x,0,0,y);
	dfs(y,0,0,x);
	L=1;
	for(int i=1;i<=n;i++)
	{
		while(t1>=h1&&f[S1[t1]]<=f[i]) t1--;
		S1[++t1]=i;
		while(t2>=h2&&f[S2[t2]]>=f[i]) t2--;
		S2[++t2]=i;
		while(f[S1[h1]]-f[S2[h2]]>m)
		{
			if(L==S1[h1]) h1++;
			if(L==S2[h2]) h2++;
			L++;
		}
		ans=max(ans,i-L+1);
	}
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/81988482