POJ 3162 树形dp+线段树

来源:互联网 发布:数据共享该怎样连接 编辑:程序博客网 时间:2024/06/05 11:02
Walking Race
Time Limit: 10000MS Memory Limit: 131072KTotal Submissions: 2524 Accepted: 606Case Time Limit: 3000MS

Description

flymouse’s sister wc is very capable at sports and her favorite event is walking race. Chasing after the championship in an important competition, she comes to a training center to attend a training course. The center hasN check-points numbered 1 through N. Some pairs of check-points are directly connected by two-way paths. The check-points and the paths form exactly a tree-like structure. The course lastsN days. On thei-th day, wc picks check-point i as the starting point and chooses another check-point as the finishing point and walks along the only simple path between the two points for the day’s training. Her choice of finishing point will make it that the resulting path will be the longest among those of all possible choices.

After every day’s training, flymouse will do a physical examination from which data will obtained and analyzed to help wc’s future training be better instructed. In order to make the results reliable, flymouse is not using data all fromN days for analysis. flymouse’s model for analysis requires data from a series of consecutive days during which the difference between the longest and the shortest distances wc walks cannot exceed a boundM. The longer the series is, the more accurate the results are. flymouse wants to know the number of days in such a longest series. Can you do the job for him?

Input

The input contains a single test case. The test case starts with a line containing the integersN (N ≤ 106) andM (M < 109). Then followN − 1 lines, each containing two integersfi and di (i = 1, 2, …, N − 1), meaning the check-pointsi + 1 andfi are connected by a path of length di.

Output

Output one line with only the desired number of days in the longest series.

Sample Input

3 21 11 3

Sample Output

3

Hint

Explanation for the sample:

There are three check-points. Two paths of lengths 1 and 3 connect check-points 2 and 3 to check-point 1. The three paths along with wc walks are 1-3, 2-1-3 and 3-1-2. And their lengths are 3, 4 and 4. Therefore data from all three days can be used for analysis.

题意:给定一张地图,它是一棵n个节点的树。mm爱跑步,mm要跑n天,每次都从一个结点开始跑步,每次都要跑到最远的那个结点,两天跑的最远距离有个差值,现在要从这n天里去若干天使得这些天的差值都小于m,问怎么取使得天数最多?n <= 100万,m <= 1亿。

首先树形dp求出每个点到其他所有点的最远距离,然后线段树维护最大值,最小值,然后维护两个指针,扫描一遍,貌似也可以单调队列,我勒个大去,数据量好大,采用系统的max,min函数,tle无极限,只好自己定义函数。

线段树维护代码:

/* ***********************************************Author :xianxingwuguanCreated Time :2014-2-11 11:57:36File Name :1.cpp************************************************ */#pragma comment(linker, "/STACK:102400000,102400000")#include <stdio.h>#include <iostream>#include <algorithm>#include <sstream>#include <stdlib.h>#include <string.h>#include <limits.h>#include <string>#include <time.h>#include <math.h>#include <queue>#include <stack>#include <set>#include <map>using namespace std;#define INF 0x3f3f3f3f#define eps 1e-8#define pi acos(-1.0)typedef long long ll;const int maxn=1000100;int head[maxn],tol,dp[maxn][3],n,m;struct node{int next,to,val;node(){};node(int _next,int _to,int _val):next(_next),to(_to),val(_val){}}edge[4*maxn];void add(int u,int v,int w){edge[tol]=node(head[u],v,w);head[u]=tol++;}int MAX(int x,int y){if(x>=y)return x;return y;}int MIN(int x,int y){if(x<=y)return x;return y;}void dfs1(int u,int fa){int b1=0,b2=0;dp[u][0]=dp[u][1]=dp[u][2]=0;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(v==fa)continue;dfs1(v,u);int ret=dp[v][0]+edge[i].val;if(ret>=b1){b2=b1;b1=ret;}else if(ret>=b2)b2=ret;}dp[u][0]=b1;dp[u][1]=b2;}void dfs2(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa)continue; dp[v][2]=max(dp[u][2],dp[v][0]+edge[i].val==dp[u][0]?dp[u][1]:dp[u][0])+edge[i].val; dfs2(v,u); }}struct NODE{int l,r,max,min;}tree[5*maxn];void build(int l,int r,int i){tree[i].l=l;tree[i].r=r;if(l==r){tree[i].max=MAX(dp[l][0],dp[l][2]);tree[i].min=tree[i].max;return;}int mid=(l+r)>>1;build(l,mid,2*i);build(mid+1,r,2*i+1);tree[i].max=MAX(tree[2*i].max,tree[2*i+1].max);tree[i].min=MIN(tree[2*i].min,tree[2*i+1].min);}int query_max(int l,int r,int i){if(tree[i].l>=l&&tree[i].r<=r)return tree[i].max;int mid=(tree[i].l+tree[i].r)>>1;int ans=0;if(l<=mid)ans=MAX(ans,query_max(l,r,2*i));if(r>mid)ans=MAX(ans,query_max(l,r,2*i+1));return ans;}int query_min(int l,int r,int i){if(tree[i].l>=l&&tree[i].r<=r)return tree[i].min;int mid=(tree[i].l+tree[i].r)>>1;int ans=INF;if(l<=mid)ans=MIN(ans,query_min(l,r,2*i));if(r>mid)ans=MIN(ans,query_min(l,r,2*i+1));return ans;}int main(){     //freopen("data.in","r",stdin);     //freopen("data.out","w",stdout);     int i,j,k; while(~scanf("%d%d",&n,&m)){ memset(head,-1,sizeof(head));tol=0; for(i=2;i<=n;i++){ scanf("%d%d",&j,&k); add(i,j,k); add(j,i,k); } dfs1(1,-1); dfs2(1,-1);// for(i=1;i<=n;i++)cout<<max(dp[i][0],dp[i][2])<<" ";cout<<endl; build(1,n,1);// while(cin>>i>>j)cout<<query_max(i,j,1)<<" "<<query_min(i,j,1)<<endl; int ans=1,l=1,r=1; while(r<=n){ int minn=query_min(l,r,1); int maxx=query_max(l,r,1); if(maxx-minn<=m){ ans=MAX(ans,r-l+1); r++; } while(maxx-minn>m){ l++; minn=query_min(l,r,1);     maxx=query_max(l,r,1); } } cout<<ans<<endl;  }     return 0;}/*C:\WINDOWS\system32\cmd.exe /c  112 61 22 42 21 61 56 16 17 27 310 111 414 16 22 22 20 11 13 21 23 18 19 235*/ 


0 0