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 线段树)的更多相关文章

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

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

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

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

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

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

  4. 【POJ3162】Walking Race 树形dp+单调队列+双指针

    题目大意:给定一棵 N 个节点的无根树,边有边权,现生成一个序列 d,d[i] 表示 i 号节点到树上其他节点距离的最大值.给定一个 m,求 d 序列中最大值和最小值之差不超过 m 的最长连续段的长度 ...

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

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

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

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

  7. HDU 4123 Bob’s Race 树形dp+单调队列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...

  8. [POJ3162]Walking Race(DP + 单调队列)

    传送门 题意:一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离 ...

  9. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

随机推荐

  1. PAT 1087 All Roads Lead to Rome[图论][迪杰斯特拉+dfs]

    1087 All Roads Lead to Rome (30)(30 分) Indeed there are many different tourist routes from our city ...

  2. [LeetCode] 195. Tenth Line_Easy tag: Bash

    Given a text file file.txt, print just the 10th line of the file. Example: Assume that file.txt has ...

  3. git 下载单个文件 已经添加多个远程服务器

    175down vote It is possible to do (in the deployed repository) git fetch followed by git checkout or ...

  4. 松下 激光位移传感器 API

    一: /* ============================================================================================== ...

  5. Python qq企业邮箱发送邮件

    Python qq企业邮箱发送邮件 进入客户端设置: 下面是代码部分: from email.header import Header from email.mime.text import MIME ...

  6. mongodb mongotemplate聚合

    1.group by并且计算总数 @Test public void insertTest() { //测试数据 //insertTestData(); Aggregation agg = Aggre ...

  7. MySQL从删库到跑路_高级(七)——事务和锁

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.事务简介 1.事务简介 事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作. 2.事物的特效 ...

  8. linux常用命令:split 命令

    split是linux下常用的分割文件命令.Linux下文件分割可以通过split命令来实现,而用cat进行文件合并.而分割可以指定按行数分割和按大小分割两种模式. 1.命令格式: split [OP ...

  9. HTML5 manifest离线缓存技术

    干什么用的? 离线缓存为的是第一次请求后,根据manifest文件进行本地缓存,并且在下一次请求后进行展示(若有缓存的话,无需再次进行请求而是直接调用缓存),最根本的感觉是它使得WEB从online可 ...

  10. web前端----css选择器样式

    一.css概述 CSS是Cascading Style Sheets的简称,中文称为层叠样式表,对html标签的渲染和布局 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. 例如 二.c ...