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发现可以用树来描绘这个草图. ...
随机推荐
- 009-spring cloud gateway-过滤器GatewayFilter、GlobalFilter、GatewayFilterChain、作用、生命周期、GatewayFilterFactory内置过滤器
一.概述 在Spring-Cloud-Gateway之请求处理流程中最终网关是将请求交给过滤器链表进行处理. 核心接口:GatewayFilter,GlobalFilter,GatewayFilter ...
- Oracal 11 g 数据库安装
一:下载安装包 http://www.oracle.com/technetwork/cn/database/enterprise-edition/downloads/112010-win64soft- ...
- YUV编码格式
YUV是被欧洲电视系统采用的一种颜色编码方法.在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄像机取像,然后把取 得的彩色图像信号经过分色,分别放大校正后得到RGB,在经过矩阵变换电路,得到 ...
- UVM中的sequence使用(一)
UVM中Driver,transaction,sequence,sequencer之间的关系. UVM将原来在Driver中的数据定义部分,单独拿出来成为Transaction,主要完成数据的rand ...
- linux常用命令:watch 命令
watch是一个非常实用的命令,基本所有的Linux发行版都带有这个小工具,如同名字一样,watch可以帮你监测一个命令的运行结果,省得你一遍遍的手动运行.在Linux下,watch是周期性的执行下个 ...
- maven intall在target文件夹中自动生成的war包部署服务器时缺斤少两
1.问题描述,本地改动特别大或者升级系统操作,打war包部署服务器上程序时候,页面或者后台总是报错,原因就是比本地少东西. 2.问题排查解决:maven clean然后maven intall在tar ...
- mysql中join后on、where的区别
SELECT * FROM A; SELECT * FROM B; 以上是两张表的机构 SELECT * FROM A LEFT JOIN B ON A.id=b.a_id ; ; ; 两个语句查询出 ...
- js将时间戳转化为日期格式
function getLocalTime(nS) { var date = new Date(nS); var Y = date.getFullYear() + '-'; ...
- Python3.x:关于urllib中urlopen报错问题的解决方案
Python3.x:关于urllib中urlopen报错问题的解决方案 调用:urllib.urlopen(url) 报错:AttributeError: 'module' object has no ...
- Android JSON 解析关键代码
Android Json 解析其实还是蛮重要的知识点,为什么这么说呢,因为安卓通信大部分的协议都是使用 json 的方式传输,我知道以前大部分是使用的 xml ,但是时代在发展社会在进步,json 成 ...