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. Oracle同义词和序列

    同义词:是表.索引.视图的模式对象的一个别名,通过模式对象创建同意词,可以隐藏对象的实际名称和 所有者信息,为对象提供一定的安全性,开发应用程序时:应该尽量避免直接使用表,视图 或其他对象,改用对象的 ...

  2. smartgit 过期

    进入到安装目录把Setting.xml 文件删除然后,再次打开就可以正常使用了.

  3. c字符数组里的中文

    char *p ="你abc"; strlen(p); //6 utf-8编码中

  4. python基础知识-7-内存、深浅、文件操作

    python其他知识目录 1.一些对内存深入理解的案例 以下列举列表,列表/字典/集合这些可变类型都是一样的原理 变量是个地址,指向存储数据的内存空间的地址,它的实质就相当于c语言里的指针.变量和数据 ...

  5. mysql innodb myisam 比较

    InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...

  6. Beta发布——视频博客

    1.视频链接 视频上传至优酷自频道,地址链接:http://v.youku.com/v_show/id_XMzkzNzAxNDk2OA==.html?spm=a2hzp.8244740.0.0 2.视 ...

  7. 《C》指针

    储存单元: 不同类型的数据所占用的字节不同,上面一个长方形格子表示4个字节 变量: 变量的值,就是存储的内容.变量的名就相当于地址的名.根据变量类型分配空间:通过变量名引用变量的值,程序经过编译将变量 ...

  8. lintcode-107-单词切分

    107-单词切分 给出一个字符串s和一个词典,判断字符串s是否可以被空格切分成一个或多个出现在字典中的单词. 样例 给出 s = "lintcode" dict = [" ...

  9. PAT 甲级 1020 Tree Traversals

    https://pintia.cn/problem-sets/994805342720868352/problems/994805485033603072 Suppose that all the k ...

  10. 关于jquery中on绑定click事件在苹果手机失效的问题(巨坑啊)

    用一个div当做了一个按钮来使用. <div class="button"> <div class=" next_button button_left ...