题目大意:给一棵树,对于所有的点,找出距它最远点的距离,然后将这些距离排成一列,找出最长的一个区间满足:其中的最大值减去最小值不大于m。

题目分析:两次dfs找出距每个节点的最远距离,然后可以通过维护两个单调队列来找最长区间,也可以通过线段树区间合并来找,后者比较麻烦。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<vector>
# include<queue>
# include<list>
# include<set>
# include<map>
# include<string>
# include<cmath>
# include<cstdlib>
# include<algorithm>
using namespace std;
# define LL long long const int N=1005;
const int INF=1000000000; ////////////////////////////////////////////
struct Edge
{
int to,w,nxt;
};
Edge e[N*N*2];
int maxn[N*N];
int rmaxn[N*N];
int maxid[N*N];
int rmaxid[N*N];
int n,m,cnt;
int head[N*N]; void add(int u,int v,int w)
{
e[cnt].to=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt++;
} void init()
{
cnt=0;
memset(head,-1,sizeof(head));
int a,b;
for(int i=2;i<=n;++i){
scanf("%d%d",&a,&b);
add(i,a,b);
add(a,i,b);
}
} void dfs1(int u,int fa)
{
maxn[u]=rmaxn[u]=0;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
if(e[i].w+maxn[v]>rmaxn[u]){
rmaxn[u]=e[i].w+maxn[v];
rmaxid[u]=v;
if(rmaxn[u]>maxn[u]){
swap(rmaxn[u],maxn[u]);
swap(rmaxid[u],maxid[u]);
}
}
}
} void dfs2(int u,int fa)
{
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
if(v==maxid[u]){
if(rmaxn[u]+e[i].w>rmaxn[v]){
rmaxn[v]=rmaxn[u]+e[i].w;
rmaxid[v]=u;
if(rmaxn[v]>maxn[v]){
swap(rmaxn[v],maxn[v]);
swap(rmaxid[v],maxid[v]);
}
}
}else{
if(maxn[u]+e[i].w>rmaxn[v]){
rmaxn[v]=maxn[u]+e[i].w;
rmaxid[v]=u;
if(rmaxn[v]>maxn[v]){
swap(rmaxn[v],maxn[v]);
swap(rmaxid[v],maxid[v]);
}
}
}
dfs2(v,u);
}
} void getDp()
{
dfs1(1,-1);
dfs2(1,-1);
}
//////////////////////////////////////////// int qmax[N*N];
int qmin[N*N]; void solve()
{
int ans=0;
int head1=0,tail1=-1;
int head2=0,tail2=-1;
int l=1,r=1;
while(r<=n){
while(head1<=tail1&&maxn[r]>=maxn[qmax[tail1]]) --tail1;
qmax[++tail1]=r;
while(head2<=tail2&&maxn[r]<=maxn[qmin[tail2]]) --tail2;
qmin[++tail2]=r;
if(maxn[qmax[head1]]-maxn[qmin[head2]]>m){
ans=max(ans,r-l);
while(maxn[qmax[head1]]-maxn[qmin[head2]]>m){
l=min(qmax[head1],qmin[head2])+1;
while(head1<=tail1&&qmax[head1]<l) ++head1;
while(head2<=tail2&&qmin[head2]<l) ++head2;
}
}
++r;
}
ans=max(ans,r-l);
printf("%d\n",ans);
} int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
getDp();
solve();
}
return 0;
}

  

POJ-3162 Walking Race (求树上两点之间最大距离)的更多相关文章

  1. POJ 3162.Walking Race 树形dp 树的直径

    Walking Race Time Limit: 10000MS   Memory Limit: 131072K Total Submissions: 4123   Accepted: 1029 Ca ...

  2. 【题解】poj 3162 Walking Race 树形dp

    题目描述 Walking RaceTime Limit: 10000MS Memory Limit: 131072KTotal Submissions: 4941 Accepted: 1252Case ...

  3. POJ 3162 Walking Race(树形dp+单调队列 or 线段树)

    http://poj.org/problem?id=3162 题意:一棵n个节点的树.有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...

  4. POJ 3162 Walking Race 树形dp 优先队列

    http://poj.org/problem?id=3162 题意 :  一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...

  5. POJ - 3162 Walking Race 树形dp 单调队列

    POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...

  6. POJ 3162 Walking Race 树形DP+线段树

    给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...

  7. POJ 2253 Frogger (求某两点之间所有路径中最大边的最小值)

    题意:有两只青蛙,a在第一个石头,b在第二个石头,a要到b那里去,每种a到b的路径中都有最大边,求所有这些最大边的最小值.思路:将所有边长存起来,排好序后,二分枚举答案. 时间复杂度比较高,344ms ...

  8. POJ 3162 Walking Race(树的直径+单调队列)

    题目大意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到dis[1],dis[2],dis[3]……dis[n] ,在数列的dis中求一个最长的 ...

  9. POJ 3162 Walking Race (树的直径,单调队列)

    题意:给定一棵带边权的n个节点的树,首先要求出每个点的最长路,然后写成序列d[1],d[2]...d[n],然后求满足 区间最大值-区间最小值<=k 的最大区间长度为多少? 思路: 分两步进行: ...

随机推荐

  1. SharePoint 2013 开发——CSOM概要

    博客地址:http://blog.csdn.net/FoxDave 本篇对客户端API做一个大致地了解. 看一下各个类别主要API之间的对应关系表. 假设我们对Server API已经有了足够地了 ...

  2. SharePoint 2013 Nintex Workflow 工作流帮助(五)

    博客地址 http://blog.csdn.net/foxdave 工作流动作 4. Assign To-Do Task(User interaction分组) 直观理解,指派待办任务给一个或多个用户 ...

  3. 用Quartz进行作业调度(转)

    概述 各种企业应用几乎都会碰到任务调度的需求,就拿论坛来说:每隔半个小时生成精华文章的RSS文件,每天凌晨统计论坛用户的积分排名,每隔30分钟执行锁定用户解锁任务. 对于一个典型的MIS系统来说,在每 ...

  4. 《J2EE,J2SE,J2ME》

    J2EE(Java EE)是做企业级应用的.比如,163邮箱,比如某公司的管理系统 J2SE(Java SE)就是Java语言的标准版本,类似于C++,主要做桌面软件,比如Eclipse,MyEcli ...

  5. php源码编译常见错误解决方案

    在CentOS编译PHP5的时候有时会遇到以下的一些错误信息,基本上都可以通过yum安装相应的库来解决.以下是具体的一些解决办法: checking for BZip2 support… yes ch ...

  6. Get start with Android development

    Firstly we should install the right version of JDK and JRE, there are two version of ADK for differe ...

  7. 最熟悉的陌生人:ListView 中的观察者模式

    RecyclerView 得宠之前,ListView 可以说是我们用的最多的组件.之前一直没有好好看看它的源码,知其然不知其所以然. 今天我们来窥一窥 ListView 中的观察者模式. 不熟悉观察者 ...

  8. 查单神器v1.0 升级 →B站看鬼畜神器v1.0

    去年学校实习,我去了一家快递输单公司工作.工作任务就是把运单图片上的内容(寄件人,地址之类)输入到公司的数据库里.每天输单结束后,还要对一些容易错的运单进行排查.单量多的时候一天甚至要查千张以上的运单 ...

  9. 10、C#基础整理(集合)

    集合 1.集合的引用 using System.Collections;//添加类 2.定义集合(ArrayList 或 Array) ArrayList arr = new ArrayList(); ...

  10. WPF中ListView如何改变选中条背景颜色

    先上图 解决方法: <ListView ...> <ListView.ItemContainerStyle> <Style TargetType="{x:Typ ...