POJ3162 Walking Race(树形DP+尺取法+单调队列)
题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长。
各个结点到其他结点的最远距离可以用树形DP解决,HDU2196。
而那个最长的连续子序列可以用单调队列求。。搞了挺久看了解法体会了下。。简单来说就是尺取法,用两个指针[i,j]表示区间,j不停+1往前移动,然后用两个单调队列分别同时更新区间最小值和最大值,再看两个队列队首的最值差是否大于m,是的话出队并调整i值,最后用j-i+1更新答案。
当然尺取法+RMQ也是OK的。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF (1LL<<60)
#define MAXN 1000111
struct Edge{
int v,w,next;
}edge[MAXN];
int NE,head[MAXN];
void addEdge(int u,int v,int w){
edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
head[u]=NE++;
}
int idx[MAXN];
long long d[][MAXN];
void dp0(int u){
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
dp0(v);
if(d[][u]<=d[][v]+edge[i].w){
d[][u]=d[][u];
d[][u]=d[][v]+edge[i].w;
idx[u]=v;
}else if(d[][u]<d[][v]+edge[i].w){
d[][u]=d[][v]+edge[i].w;
}else if(d[][u]<d[][v]+edge[i].w){
d[][u]=d[][v]+edge[i].w;
}
}
}
void dp1(int u){
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(idx[u]==v) d[][v]=max(d[][u],d[][u])+edge[i].w;
else d[][v]=max(d[][u],d[][u])+edge[i].w;
dp1(v);
}
}
struct Que{
int que[MAXN],front,rear;
bool isEmpty(){
return front==rear;
}
int getFront(){
return que[front];
}
int getRear(){
return que[rear-];
}
void push(int a){
que[rear++]=a;
}
}mxq,mmq;
int main(){
memset(head,-,sizeof(head));
int n,m,a,b;
scanf("%d%d",&n,&m);
for(int i=; i<=n; ++i){
scanf("%d%d",&a,&b);
addEdge(a,i,b);
}
dp0();
dp1();
int res=;
for(int i=,j=; i<=n; ++i){
d[][i]=max(d[][i],d[][i]);
while(!mxq.isEmpty() && d[][mxq.getRear()]<d[][i]) --mxq.rear;
mxq.push(i);
while(!mmq.isEmpty() && d[][mmq.getRear()]>d[][i]) --mmq.rear;
mmq.push(i);
while(d[][mxq.getFront()]-d[][mmq.getFront()]>m){
if(mxq.getFront()<mmq.getFront()) j=mxq.getFront()+,++mxq.front;
else j=mmq.getFront()+,++mmq.front;
}
res=max(res,i-j+);
}
printf("%d",res);
return ;
}
POJ3162 Walking Race(树形DP+尺取法+单调队列)的更多相关文章
- 【POJ3162】Walking Race 树形dp+单调队列+双指针
题目大意:给定一棵 N 个节点的无根树,边有边权,现生成一个序列 d,d[i] 表示 i 号节点到树上其他节点距离的最大值.给定一个 m,求 d 序列中最大值和最小值之差不超过 m 的最长连续段的长度 ...
- POJ - 3162 Walking Race 树形dp 单调队列
POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...
- [POJ3162]Walking Race(DP + 单调队列)
传送门 题意:一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要在这n个距离里取连续的若干天,使得这些天里最大距离和最小距离 ...
- 【题解】poj 3162 Walking Race 树形dp
题目描述 Walking RaceTime Limit: 10000MS Memory Limit: 131072KTotal Submissions: 4941 Accepted: 1252Case ...
- POJ 3162 Walking Race 树形DP+线段树
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...
- POJ 3162.Walking Race 树形dp 树的直径
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 4123 Accepted: 1029 Ca ...
- 【BZOJ2282】[Sdoi2011]消防 树形DP+双指针法+单调队列
[BZOJ2282][Sdoi2011]消防 Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这 ...
- 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 ...
随机推荐
- 文字编辑器kindeditor-min.js的使用
例子: <link rel="stylesheet" type="text/css" href="<?=$WebSiteRootDir?& ...
- PHP读取csv文件
<?php //取数据 $f_d = file_get_contents('tpl_import_info.csv'); $f_d = iconv('gbk', 'utf-8', $f_d); ...
- css调用外部样式和css样式说明剧中显示
<title>边走边乔</title><link href="css/style.css" rel="stylesheet" ty ...
- 45. Singleton类的C++/C#实现[Singleton]
[题目] 设计一个类,我们只能生成该类的一个实例. [分析] 单例模式的意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点.让类自身负责保存它的唯一实例.这个类可以保证没有其他实例可.以被创建 ...
- c++11之bind
std::bind是个c++推出的新的特性,非常有用,让你写起来率试不爽. #include <iostream> using namespace std; #include <fu ...
- Java for LeetCode 048 Rotate Image
You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...
- MFC 选择一个文件或者文件夹路径
//选择文件CFileDialog dlg(TRUE, 0, 0, OFN_HIDEREADONLY, "文本文件|*.txt|所有文件|*.*)||",0);if (dlg.Do ...
- 菜菜买气球(codevs 2851)
题目描述 Description 六一儿童节到了,菜菜爸爸带着菜菜来到了游乐园,菜菜可高兴坏了.这不,菜菜看到了一排卖气球的,便吵着闹着要买气球. 不过这些卖气球的也奇怪,他们都站成了一排,而且每个人 ...
- BroadcastReceiver study
BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播. 在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这 ...
- C++多线程下的单例模式
一.懒汉模式:即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例. 需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread s ...