POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
http://poj.org/problem?id=3162
题意:
一棵n个节点的树。有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离的差小于M,问怎么取使得天数最多?
思路:
这道题目求最远距离和HDU 2196是一模一样的,这个不是很难。关键是要怎么处理得到的数据。
可以用单调队列做也可以用线段树来做,先介绍一下单调队列。
因为有最大值和最小值,所以我们需要两个单调队列,一个维护最大值,另一个维护最小值。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,ll> pll;
const int INF = 0x3f3f3f3f;
const int maxn=1e6+; int n, m;
int tot;
ll d[maxn][];
int path[maxn];
int head[*maxn];
int q_max[maxn];
int q_min[maxn]; struct node
{
int v,w,next;
}e[*maxn]; void addEdge(int u,int v,int w)
{
e[tot].v=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot++;
} void dfs1(int u,int fa)
{
d[u][]=d[u][]=;
path[u]=-;
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(v==fa) continue;
dfs1(v,u);
if(d[u][]<d[v][]+e[i].w)
{
path[u]=v;
d[u][]=d[u][];
d[u][]=d[v][]+e[i].w;
}
else if(d[u][]<d[v][]+e[i].w)
d[u][]=d[v][]+e[i].w;
}
} void dfs2(int u,int fa)
{
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(v==fa) continue;
if(path[u]==v) d[v][]=max(d[u][],d[u][])+e[i].w;
else d[v][]=max(d[u][],d[u][])+e[i].w;
dfs2(v,u);
}
} int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
tot=;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)
{
int v,w;
scanf("%d%d",&v,&w);
addEdge(i,v,w);
addEdge(v,i,w);
}
dfs1(,-);
dfs2(,-);
int ans=-;
int frt_max=,rear_max=;
int frt_min=,rear_min=;
for(int i=,j=;i<=n;i++)
{
d[i][]=max(d[i][],d[i][]);
while(frt_max<rear_max && d[q_max[rear_max-]][]<d[i][]) rear_max--;
q_max[rear_max++]=i;
while(frt_min<rear_min && d[q_min[rear_min-]][]>d[i][]) rear_min--;
q_min[rear_min++]=i; while(frt_max<rear_max && frt_min<rear_min && d[q_max[frt_max]][]-d[q_min[frt_min]][]>m)
{
if(q_max[frt_max]>q_min[frt_min]) {j=q_min[frt_min]+;frt_min++;}
else {j=q_max[frt_max]+;frt_max++;}
}
ans=max(ans,i-j+);
}
printf("%d\n",ans);
}
return ;
}
单调队列
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,ll> pll;
const int INF = 0x3f3f3f3f;
const int maxn=1e6+; int n, m;
int tot;
ll d[maxn][];
int path[maxn];
int head[*maxn]; int MAX[maxn<<];
int MIN[maxn<<];
int query_max,query_min; struct node
{
int v,w,next;
}e[*maxn]; void addEdge(int u,int v,int w)
{
e[tot].v=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot++;
} /**********************************************
dfs
**********************************************/ void dfs1(int u,int fa)
{
d[u][]=d[u][]=;
path[u]=-;
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(v==fa) continue;
dfs1(v,u);
if(d[u][]<d[v][]+e[i].w)
{
path[u]=v;
d[u][]=d[u][];
d[u][]=d[v][]+e[i].w;
}
else if(d[u][]<d[v][]+e[i].w)
d[u][]=d[v][]+e[i].w;
}
} void dfs2(int u,int fa)
{
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(v==fa) continue;
if(path[u]==v) d[v][]=max(d[u][],d[u][])+e[i].w;
else d[v][]=max(d[u][],d[u][])+e[i].w;
dfs2(v,u);
}
} /**********************************************
线段树
**********************************************/ void PushUp(int o)
{
MAX[o]=max(MAX[o<<],MAX[o<<|]);
MIN[o]=min(MIN[o<<],MIN[o<<|]);
} void build(int l, int r, int o)
{
if(l==r)
{
MAX[o]=MIN[o]=max(d[l][],d[l][]);
return;
}
int mid=(l+r)/;
build(l,mid,o<<);
build(mid+,r,o<<|);
PushUp(o);
} void query(int ql, int qr, int l, int r, int o)
{
if(ql<=l && qr>=r)
{
query_max=max(query_max,MAX[o]);
query_min=min(query_min,MIN[o]);
return;
}
int mid=(l+r)/;
if(ql<=mid) query(ql,qr,l,mid,o<<);
if(mid<qr) query(ql,qr,mid+,r,o<<|);
} int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
tot=;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)
{
int v,w;
scanf("%d%d",&v,&w);
addEdge(i,v,w);
addEdge(v,i,w);
}
dfs1(,-);
dfs2(,-);
build(,n,);
int ans=; int l=,r=;
while(r<=n)
{
query_max=; query_min=INF;
query(l,r,,n,);
if(query_max-query_min<=m) {ans=max(ans,r-l+);r++;}
while(query_max-query_min>m)
{
l++;
query_max=; query_min=INF;
query(l,r,,n,);
}
}
printf("%d\n",ans);
}
return ;
}
线段树
POJ 3162 Walking Race(树形dp+单调队列 or 线段树)的更多相关文章
- POJ - 3162 Walking Race 树形dp 单调队列
POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...
- POJ 3162.Walking Race 树形dp 树的直径
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 4123 Accepted: 1029 Ca ...
- 【题解】poj 3162 Walking Race 树形dp
题目描述 Walking RaceTime Limit: 10000MS Memory Limit: 131072KTotal Submissions: 4941 Accepted: 1252Case ...
- 【POJ3162】Walking Race 树形dp+单调队列+双指针
题目大意:给定一棵 N 个节点的无根树,边有边权,现生成一个序列 d,d[i] 表示 i 号节点到树上其他节点距离的最大值.给定一个 m,求 d 序列中最大值和最小值之差不超过 m 的最长连续段的长度 ...
- POJ 3162 Walking Race 树形DP+线段树
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...
- POJ 3162 Walking Race 树形dp 优先队列
http://poj.org/problem?id=3162 题意 : 一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...
- HDU 4123 Bob’s Race 树形dp+单调队列
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...
- [POJ3162]Walking Race(DP + 单调队列)
传送门 题意:一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离 ...
- (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列
Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...
随机推荐
- Celery配置Redis数据库保存Return结果状态
使用windows版本 1.于GitHUB下载https://github.com/ServiceStack/redis-windows Window版本,到路径: 2. 运行路径下:D:\redis ...
- MVC html.beginform & ajax.beginform
1.指定表单提交方式和路径等 @using (Html.BeginForm("Index", "Home", FormMethod.Get, new { nam ...
- Java接口多线程并发测试 (二)
原文地址http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html 这是一篇很不错的文章,感谢原博主的分享! JAVA多线程实现和 ...
- C语言常用函数大全
一.数学函数 调用数学函数时,要求在源文件中包下以下命令行: #include <math.h> 函数原型说明 功能 返回值 说明 int abs( int x) 求整数x的绝对值 计算结 ...
- mysql在windows下命令行启动与关闭服务
一.命令行关闭与启动服务的命令: 二.运行cmd的命令行程序时,必须以管理员身份运行.否则会出现如下提示: 三.mysql5.7版本的服务名一般默认为mysql57,因此如果使用服务名mysql,那么 ...
- hdu3511 Prison Break 圆的扫描线
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3511 题目: Prison Break Time Limit: 10000/5000 MS ( ...
- MyBatis学习笔记(四)——解决字段名与实体类属性名不相同的冲突
转自孤傲苍狼的博客:http://www.cnblogs.com/xdp-gacl/p/4264425.html 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演 ...
- C++ Word Count 发布程序
前段时间,模仿 Linux 系统下的 wc 程序,在 Windows 系统环境下使用 C/C++ 实现了一个相似的 WC 程序,只不过有针对性,针对的是 C/C++,Java 等风格的源代码文件. 此 ...
- Linux服务器配置---安装centos
安装centos 1.插入光盘,启动,可以选择第一项进行安装 2.根据实际需求,一般会选择skip 3.选择语言“简体中文” 4.选择第一项 5.设置主机名字,使用默认 6.选择时区 7.设置超级用户 ...
- 访问Hsql .data数据库文件
一.Hsql简介: hsql数据库是一款纯Java编写的免费数据库,许可是BSD-style的协议. 仅一个hsqldb.jar文件就包括了数据库引擎,数据库驱动,还有其他用户界面操作等内容.下载地址 ...