题目大意:给一棵树,对于所有的点,找出距它最远点的距离,然后将这些距离排成一列,找出最长的一个区间满足:其中的最大值减去最小值不大于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. 集成支付宝钱包支付iOS SDK的方法与经验

    流程 摘自第一个文档<支付宝钱包支付接口开发包2.0标准版.pdf> 图中的“商户客户端”就是我们的iOS客户端需要做的事情: 调用支付宝支付接口 处理支付宝返回的支付结果 在调用支付宝支 ...

  2. C# CsvFile 类

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  3. AFNetworking3.0概述

    最近一直在研究iOS网络开发,对NSURLSession套件进行了深入研究,作为iOS开发者,熟悉苹果的原生技术,可以在不需要第三方框架的情况下进行网络开发,也更有利于从底层了解iOS网络请求的原理, ...

  4. Linux下进程的建立

    Linux下进程的建立 我们都知道,进程就是正在执行的程序.而在Linux中,可以使用一个进程来创建另外一个进程.这样的话,Linux的进程的组织结构其实有点像Linux目录树,是个层次结构的,可以使 ...

  5. JS 基于面向对象的 轮播图1

    ---恢复内容开始--- 1 'use strict' 2 function Tab(id){ 3 if(!id)return; 4 this.oBox = document.getElementBy ...

  6. 走进科学之WAF(Web Appllication Firewall)篇

    小编P.S:文章非常详尽对WAF领域进行了一次科普,能有让人快速了解当前WAF领域的相关背景及现状,推荐所有WAF领域的同学阅读本文. 1. 前言 当WEB应用越来越为丰富的同时,WEB 服务器以其强 ...

  7. mysql 命令行操作

    1.连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root ...

  8. 渐进记法(O,Ω,Θ)

    第一次在<算法导论>中看到这三种渐进记法的符号,当时对此一窍不通,所以也就没有注意它们,直接把他们忽略了,知道学习算法的时候,才知道当初的做法有多傻,因为一个算法的好坏以及复杂度,可以用它 ...

  9. css中的列表属性

    list-style-type设定引导列表的符号类型,可以设置多种符号类型,值为disc.circle.square等 list-style-image使用图像作为定制列表的符号 list-style ...

  10. 程序员是怎么炼成的---OC题集--练习答案与题目(3)

    1.init 2.initWithBytes:length:encoding: 3.initWithCharacters:length: 4.initWithCString:encoding: 5.i ...