POJ - 3162 Walking Race 树形dp 单调队列
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 单调队列的更多相关文章
- 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发现可以用树来描绘这个草图. ...
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
http://poj.org/problem?id=3162 题意:一棵n个节点的树.有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...
随机推荐
- BZOJ 4899 记忆的轮廓
话说BZOJ 是不是死了啊 (已经没有传送门了) 设 $f[i][j]$ 表示走到第 $j$ 个位置确定了 $i$ 个存档点时的最小代价,并强制第 $j$ 个位置有一个存档点 那么设 $cst[i][ ...
- C Looooops
看了半天的同余 扩展欧几里得 练练手 C Looooops Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 27079 A ...
- oracle创建用户表空间
--本次因工作需要,为其他部门提供部分表数据,创建一个新用户与表空间.--system用户下drop user sys_outside cascade;drop tablespace sys_outs ...
- webpack 学习过程
什么是WebPack,为什么要使用它? 为什要使用WebPack 现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包.为了简化开发的复杂度,前端社区涌现 ...
- js安全类型检测
背景: 都知道js内置的类型检测,大多数情况下是不太可靠的,例如: typeof . instanceof typeof 返回一个未经计算的操作数的类型, 可以发现所有对象都是返回object ...
- lumen时区
今天用 Lumen 框架写代码时, 也是初次体验 Lumen, 遇到了一个问题, 从数据库里查出的时间比数据库里保存的 TIMESTAMP 时间慢了8个小时, 很明显这是一个时区设置的问题, 本以为可 ...
- zabbix4.2Proxy安装文档
zabbix4.2Proxy安装文档 目录 zabbix4.2Proxy安装文档 1 一.安装 2 1.前期安装准备 2 2.安装zabbix RPM源 3 2.1下载zabb ...
- 微信小程序开发(一)创建一个小程序Hello World!
开发微信小程序并不是很难,网上有很多小程序开发资料,尤其是微信官方的<小程序开发指南>最详细. 下面是我开发小程序的历程: 第一步,请前往https://mp.weixin.qq.com/ ...
- Selenium(2)
testing123456peter123456rose123456 一.常见的运行错误: 1.[error] Timed out after 30000ms Timed out:超时 after:之 ...
- Spring基础01——在IDEA中编写spring.xml
如果需要在IDEA自动创建spring.xml配置文件,那么我们就需要先引入Spring相关的依赖 <dependency> <groupId>org.springframew ...