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发现可以用树来描绘这个草图. ...
随机推荐
- vertx读取配置文件,获得端口号
1:在src/conf目录下创建conf.json { } 2:创建Verticle, config().getInteger("http.port", 8080),将会读取配置文 ...
- 如何实现在H5里调起高德地图APP?
http://www.cnblogs.com/milkmap/p/5912350.html 这一篇文章,将讲述如何在H5里调起高德地图APP,并展示兴趣点.适合于展示某个餐馆,商场等,让用户自行选择前 ...
- javascript实现unicode与字符互相转换
javascript实现unicode与字符互相转换. <script language="javascript"> //手机检测 function checkMo ...
- OO第四次阶段性总结
测试与正确性论证的效果差异及优缺点 测试实际上就是对程序进行的一种黑箱测试,利用各种各样的测试样例去检验程序是否能够给出正确的结果.其中的单元测试则是将整体的测试拆分成单元来进行,但其仍然躲不开黑箱测 ...
- webbench,简单、实用!
官网:http://home.tiscali.cz/~cz210552/webbench.html 1.下载并安装 # wget http://home.tiscali.cz/~cz210552/ ...
- linux中vim的常用方法
i 当前光标位置插入 a 当前光标后插入 0 另起一行插入 A 在光标所在行尾插入 I 在光标所在行首插入 :set nu设置 行号 :set nunu 取消行号 gg 到第一行 G 到最后一行 $ ...
- RocketMQ 集群搭建--双Master方案
安装环境 jdk1.7 alibaba-rocketmq-3.2.6.tar.gz VM虚拟机redhat6.5-x64:192.168.1.201 192.168.1.202 Xshell4 部署 ...
- 数据仓库基础(二)ETL
本文转载自:http://www.cnblogs.com/evencao/archive/2013/06/14/3135529.html ETL在数据仓库中具有以下的几个特点: 数据流动具有周期性: ...
- 数据在千万级别上进行全文检索有哪些技术?强大的大数据全文索引解决方案-ClouderaSearch
数据在千万级别上进行全文检索有哪些技术?强大的大数据全文索引解决方案-ClouderaSearch1.lucene (solr, elasticsearch 都是基于它) 2.sphinx3.elas ...
- PHP empty、isset、isnull的区别
PHP empty.isset.isnull的区别 empty 如果 变量 是非空或非零的值,则 empty() 返回 FALSE.换句话说,”".0.”0″.NULL.FALSE.arra ...