Portal -->bzoj2500

Description

​   给你一棵树,每条边有边权,有两个给给的人第\(i\)天会从编号为\(i\)的点出发走这个点的树上最长距离,现在要你求一个最长的\(len\)满足\(dis_{st},dis_{st+1}...dis_{st+len-1}\)满足其中的最大值最小值之差不大于\(m\),\(dis_{i}\)表示第\(i\)天走的距离,\(st\)不一定为\(1\)

Solution

​   很好这题。。我一开始看错题了以为是一个弱智题(看成相邻两个差\(<=m\)了。。)

​   然后我没有看空间十分开心写了一个预处理rmq+双指针乱搞的玩意==

​​   后来终于走回正道写了单调队列。。没救了真的

​​   感觉自己对单调队列的运用还是不够熟练,所以还是搬上来加深一下印象好了

​ ​  

​   这题首先求每个点为起点的树上最长距离。。经典树形dp维护子树内最大值最小值可以\(O(n)\)求出存在\(dis\)数组里面

​​   然后我们考虑用这样的方式求一个最长符合条件区间:我们考虑将\(n\)个数依次加进当前的区间中,记现在加到第\(i\)个数,然后在\(i-1\)这个位置结尾的最长符合条件区间的左端点为\(st\),那么将\(dis[i]\)加进来的话,如果此时区间内最大值最小值符合条件,那么更新答案,否则我们需要调整区间的左端点,将其移到一个最靠左的满足原来的\(min\)或者\(max\)不在新区间内的位置(也就是\(min\)和\(max\)中最靠前的那个的位置\(+1\)),这样我们就可以得到以每个\(i\)为右端点的最长区间,\(ans\)必定为其中的最大值

​   那么我们只要开两个双端队列维护当前区间内的最大值和最小值就好了,维护最大值的队列保持单调递减,维护最小值的队列保持单调递增,每次需要调整区间的时候只要找队头中较靠左的位置\(+1\)并将\(st\)调到这个位置即可

​  

​​   代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int N=1000010,TOP=20;
struct xxx{
int y,nxt;
ll dis;
}a[N];
struct Data{/*{{{*/
int which;
ll mx,smx;
Data(){}
Data(int _which,ll _mx,ll _smx){which=_which; mx=_mx; smx=_smx;}
void update(int u,ll d){
if (mx<d)
smx=mx,which=u,mx=d;
else
smx=max(smx,d);
}
}info[N];/*}}}*/
int mnq[N],mxq[N];
ll dis[N];
int h[N];
int l1,r1,l2,r2;
int n,m,tot,ans;
void add(int x,int y,ll d){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot; a[tot].dis=d;}
void dfs(int x,ll d){
int u;
info[x]=Data(x,0,0); dis[x]=0;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
dfs(u,d+a[i].dis);
info[x].update(u,info[u].mx+a[i].dis);
dis[x]=max(dis[u]+a[i].dis,dis[x]);
}
}
void dfs1(int fa,int x,ll predis){
int u;
if (fa){
if (x==info[fa].which){
dis[x]=max(dis[x],info[fa].smx+predis);
info[x].update(fa,info[fa].smx+predis);
}
else{
dis[x]=max(dis[x],info[fa].mx+predis);
info[x].update(fa,info[fa].mx+predis);
}
}
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
dfs1(x,u,a[i].dis);
}
}
void solve(){
int st=1;
l1=l2=1; r1=r2=0;
for (int i=1;i<=n;++i){
while (r1>=l1&&dis[mnq[r1]]>=dis[i]) --r1;
mnq[++r1]=i;
while (r2>=l2&&dis[mxq[r2]]<=dis[i]) --r2;
mxq[++r2]=i;
while (dis[mxq[l2]]-dis[mnq[l1]]>m){
if (mnq[l1]<mxq[l2])
st=mnq[l1]+1,++l1;
else
st=mxq[l2]+1,++l2;
}
ans=max(ans,i-st+1);
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
ll d;
int fa;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
tot=0;
for (int i=2;i<=n;++i){
scanf("%d%lld",&fa,&d);
add(fa,i,d);
}
dfs(1,0);
dfs1(0,1,0);
solve();
printf("%d\n",ans);
}

【bzoj2500】幸福的道路的更多相关文章

  1. BZOJ2500: 幸福的道路

    题解: 一道不错的题目. 树DP可以求出从每个点出发的最长链,复杂度O(n) 然后就变成找一个数列里最长的连续区间使得最大值-最小值<=m了. 成了这题:http://www.cnblogs.c ...

  2. bzoj2500幸福的道路 树形dp+单调队列

    2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 434  Solved: 170[Submit][Status][Discuss ...

  3. [Bzoj2500]幸福的道路(树上最远点)

    2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 474  Solved: 194[Submit][Status][Discuss ...

  4. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  5. 【BZOJ2500】幸福的道路 树形DP+RMQ+双指针法

    [BZOJ2500]幸福的道路 Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的 ...

  6. 【BZOJ】【2500】幸福的道路

    树形DP+单调队列优化DP 好题(也是神题……玛雅我实在是太弱了TAT,真是一个250) 完全是抄的zyf的……orz我还是退OI保平安吧 第一步对于每一天求出一个从第 i 个点出发走出去的最长链的长 ...

  7. [BZOJ 2500] 幸福的道路

    照例先贴题面(汪汪汪) 2500: 幸福的道路 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 368  Solved: 145[Submit][Sta ...

  8. 【bzoj2500】幸福的道路 树形dp+单调队列

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

  9. 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...

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

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

随机推荐

  1. SQL数据类型(SQL Server六个类型使用)

    SQL数据类型是一个属性,它指定任何对象的数据的类型.在SQL中每一列,变量和表达有相关数据类型. 当创建表时,需要使用这些数据类型. 会选择根据表列要求选择一个特定的数据类型. SQL Server ...

  2. TW实习日记:第十天

    今天任务很简单,就是出品项目的时间轴显示页面和动态路由设置.其实时间轴页面很快就做完了,在做完处理完数据之后,然而有很多细节需要打磨,这就又考验了我面向搜索引擎编程的能力,根据需求百度了很多css的样 ...

  3. 我想这次我真的理解了 JavaScript 的单线程机制

    今天面试的时候被问到一个问题,是关于 JS 异步的.当时我脑海中闪过了一个单线程的概念,但却没有把真正的原理阐述清楚.所以回来特意重新回顾了前面单线程和异步相关的一些知识点. 虽然之前学习的时候也接触 ...

  4. Fast R-CNN学习总结

    Fast R-CNN是R-CNN的改良版,同时也吸取了SPP-net中的方法.在此做一下总结. 论文中讲到在训练阶段,训练一个深度目标检测网络(VGG16),训练速度要比R-CNN快9倍左右,比SPP ...

  5. kNN--近邻算法

    kNN--近邻算法 kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性. 在机器学习中常用于分类. 数学内容: ...

  6. 用 Python 3 的 async / await 做异步编程

    前年我曾写过一篇<初探 Python 3 的异步 IO 编程>,当时只是初步接触了一下 yield from 语法和 asyncio 标准库.前些日子我在 V2EX 看到一篇<为什么 ...

  7. 第一次作业(homework-01)成绩公布

    已收到博客名.github名的同学得分列表: 学号后三位 成绩(0-10) 215 8082 0132 5184 5027 7194 9.5157 7074 8195 6222 8158 6128 8 ...

  8. Alpha发布——美工+文案

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2283 一.功能介绍 本团队(可以低头,但没必要)开发的是一款基于腾讯微信 ...

  9. 软件工程团队项目第一个Sprint评论

    (1)跑男:话说我没怎么听懂这个游戏是怎么玩的,可能是由于这是第一组,所以我没有反应过来把,界面设计的还可以,但是像设置,选关,帮助真心没看懂.有一种感觉就是,这个游戏是由一堆的漂亮的图片拼起来的,还 ...

  10. 用python脚本计算某一个文件的行数

    python可以统计文件的行数,你相信吗?不管你信不信反正我信了.下面我们来看一下python怎样统计文件的行数,代码很简单,我也做了注释,很简单的实现... 1 2 3 4 5 6 7 8 9 10 ...