POJ - 3162Walking Race

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

  一开始楞是没看懂题意,最讨厌这种四级题,这是在刁难我英语小能手(能用翻译的就不自己动手)。而且这题感觉单调队列那里的处理更难一点,不过还是来说一说怎么树形dp取得最远距离,先画个简简单单丑丑的图

  我们直接从1作为根节点开始dfs的话,可以处理1的最远距离,并且可以得出到其它节点在其子树中的最短距离,然后怎么得到其他节点的最远距离呢?我们还是从1开始,2的最短距离无非就是1和2连接这一条边再加上除这条外的最长分支也就是1和4这条边,而3的话1和3连接的这条边是在1和4这条路径上的,所以对3来说最远距离就是1的除1和4这条外其他最长分支加上1和3连接的这条边与3和4连接的这条边中的最大值,所以我们可以更新一个每个节点的最大距离以及第二远距离还有最远距离来自哪个子节点的方向。

  这样的话先一遍dfs得出作为根节点的情况,还有其他节点到子树的情况,然后第二边dfs再由根节点去传入数据更新其他节点的最大值,也就判断子节点是否是最远距离方向的,是的话传入第二远距离,否则传入最远距离。

  然后就是取区间那里了,首先尺取思想,但需要一个单调递减队列维护区间最大值(最大值在队列首部),然后还需要一个单调递增队列维护区间最小值(最小值在队列首部),然后区间往右的同时,更新左端,详情见代码。

 #include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int N=;
struct Side{
int v,ne,len;
}S[*N];
int sn,n,m,head[N],dis1[N],dis2[N],path[N];
void add(int u,int v,int c)
{
S[sn].v=v;
S[sn].len=c;
S[sn].ne=head[u];
head[u]=sn++;
}
void updata(int u,int v,int dis)//更新距离
{
if(dis>dis1[u])//更新最大距离的来源点
path[u]=v;
dis2[u]=max(dis2[u],min(dis1[u],dis));
dis1[u]=max(dis1[u],dis);
}
void dfs1(int u,int f)
{
for(int i=head[u];i!=-;i=S[i].ne)
{
int v=S[i].v;
if(v!=f)
{
dfs1(v,u);//先搜索子节点
updata(u,v,dis1[v]+S[i].len);//更新
}
}
}
void dfs2(int u,int f,int len)
{
updata(u,f,len);//由父节点传入的距离更新距离
for(int i=head[u];i!=-;i=S[i].ne)
{
int v=S[i].v;
if(v!=f)
{
if(v==path[u])
dfs2(v,u,dis2[u]+S[i].len);
else
dfs2(v,u,dis1[u]+S[i].len);
}
}
}
int main()
{
int f,d;
while(~scanf("%d%d",&n,&m))
{
for(int i=;i<=n;i++)
{
head[i]=-;
dis1[i]=dis2[i]=;
}
sn=;
for(int i=;i<n;i++)
{
scanf("%d%d",&f,&d);
add(i+,f,d);
add(f,i+,d);
}
dfs1(,);
dfs2(,,);
deque<int> qx,qd;//qx单调递增队列,qd单调递减队列
int ans=; //注意是双向队列,单向没有back()
for(int i=,j=;i<=n;i++)//j是左端,i是右端
{
//维护单调性
while(qd.size()&&dis1[qd.back()]<dis1[i])
qd.pop_back();
while(qx.size()&&dis1[qx.back()]>dis1[i])
qx.pop_back();
qd.push_back(i);
qx.push_back(i);
while(qd.size()&&qx.size()&&dis1[qd.front()]-dis1[qx.front()]>m)
{
//当最大值减最小值大于m时这时左端的位置就需要调整了
//左端肯定是要调整到最大值和最小值中较近的位置的前面
if(qd.front()<qx.front())
{
j=qd.front();
qd.pop_front();
}
else
{
j=qx.front();
qx.pop_front();
}
//把区间外的数全部弹出
while(qd.size()&&qd.front()<=j)
qd.pop_front();
while(qx.size()&&qd.front()<=j)
qx.pop_front();
}
ans=max(ans,i-j);//更新区间长度
}
printf("%d\n",ans);
}
return ;
}

简简单单的低调

  连做了几题树形dp,不怎么说得出,不过感觉还是有点心得的。核心的思想还是在于它的一棵数的结构,我们可以把某个节点假设为根节点再由它的情况去推导出整棵树的情况。而且精华部分也正如dp,搞清楚dp什么,然后是状态转移的过程。想练好它,无疑就两个方法,做题,思考。

POJ - 3162 Walking Race 树形dp 单调队列的更多相关文章

  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. 【POJ3162】Walking Race 树形dp+单调队列+双指针

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

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

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

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

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

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

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

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

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

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

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

  9. POJ 3162 Walking Race(树形dp+单调队列 or 线段树)

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

随机推荐

  1. Python—None

    None是一个特殊的常量. None不是False. None不是0. None不是空字符串. None有自己的数据类型NoneType,并且是NoneType中唯一的值. None只是一个空值的对象 ...

  2. UAV图像拼接软件编译环境配置

    1,需要下载的软件: 依次安装qt-opensource.addin qt安装目录为C:\Qt\4.8.6 2,vs2010配置 *配置UAVBeta工程的属性,下图黑色字体部分与qt相关,取决于你的 ...

  3. 04docker容器操作

    操作Docker container 容器是镜像的一个运行实例,镜像是静态的只读文件,容器带有运行时需要的可写文件层,同时,容器中的应用进程处于运行状态 1:新建一个容器 ubuntu@ubuntu: ...

  4. zookeeper初识

    ZOOKEEPER是为分布式系统提供高性能的协调工具 角色: 1.领导者(leader):负责进行投票的发起和决议,更新系统状态2.学习者(learner):包括跟随者(follower)和观察者(o ...

  5. Power BI 行级别安全性 (RLS)

    在 Power BI Desktop 中定义角色和规则 你可以在 Power BI Desktop 中定义角色和规则. 发布到 Power BI 时,它还会发布角色定义. 若要定义安全角色,请执行以下 ...

  6. 关于C++内存对齐

    关于C++内存对齐 C++11从标准层面引入了一些和内存对齐相关的特性,标准库也增加了对应的组件,这里稍微总结一下. 取得某个类型的对齐值 C++中的Object(对象)是指一块满足以下条件的内存区域 ...

  7. javascript相关的增删改查以及this的理解

    前两天做了一个有关表单增删改查的例子,现在贴出来.主要是想好好说一下this. 下面贴一张我要做的表格效果. 就是实现简单的一个增删改查. 1.点击增加后自动增加一行: 2.点击保存当前行会将属性改成 ...

  8. Caffe Blob测试

    本例子来源于<21天实战Caffe> 代码如下: #include <vector> #include <iostream> #include <caffe/ ...

  9. Spring面试题整理

    1.https://blog.csdn.net/a745233700/article/details/80959716 2.https://ifeve.com/spring-interview-que ...

  10. vue+axios请求头封装

    import { mapMutations } from 'vuex' import axios from 'axios' import { Toast } from 'mint-ui'; impor ...