原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html


题目描述

小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光.
他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图.
他们不愿枯燥的每天从同一个地方开始他们的锻炼,所以他们准备给起点标号后顺序地从每个起点开始(第一天从起点一开始,第二天从起点二开始……). 而且他们给每条道路定上一个幸福的值.很显然他们每次出发都想走幸福值和最长的路线(即从起点到树上的某一点路径中最长的一条).
他们不愿再经历之前的大起大落,所以决定连续几天的幸福值波动不能超过M(即一段连续的区间并且区间的最大值最小值之差不超过M).他们想知道要是这样的话他们最多能连续锻炼多少天(hint:不一定从第一天一直开始连续锻炼)?
现在,他们把这个艰巨的任务交给你了!

输入

第一行包含两个整数N, M(M<=10^9).
第二至第N行,每行两个数字Fi , Di, 第i行表示第i个节点的父亲是Fi,且道路的幸福值是Di.

输出

最长的连续锻炼天数

样例输入

3 2
1 1
1 3

样例输出

3


题解

树形dp+倍增RMQ+二分,这完全是两道题拼成一道题的啊。。。

先用树形dp求出到某个点最大距离。

设fst[x]表示以x为根的树中点到x的最大距离,fnd[x]表示以x为根的树中,除去fst[x]所在子树以外其余子树中的点到x的最大距离。

这里比较难想,待会分析。

第一次dfs可以直接处理好deep、fst和fnd。

然后考虑如何用x递推出x的儿子y的最远距离。

那么对于y,有2种情况可能构成到y距离最大:在y的父树中、在y的子树中,在y的父树中包括在x的父树中和在x除y以外的子树中。

在y的子树中即为fst[y],在x除y以外的子树中,需要判断y是否为构成到点x的最大距离的点所在的子树:如果是fst则取fnd,否则取fst。

这样就能够dp求出到某个点最大距离。

然后对于每个点,二分后边的位置,RMQ预处理,O(1)求出区间极差,判断一下即可。

#include <cstdio>
#include <algorithm>
using namespace std;
int head[1000010] , to[2000010] , next[2000010] , cnt , n , k , p , q;
int len[2000010] , fst[1000010] , fnd[1000010] , ff[1000010] , deep[1000010] , minn[1000010][22] , maxn[1000010][22] , log[1000010];
void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
void dfs1(int x , int fa)
{
int i , y;
for(i = head[x] ; i ; i = next[i])
{
y = to[i];
if(y != fa)
{
deep[y] = deep[x] + len[i];
dfs1(y , x);
if(fst[y] + len[i] > fst[x]) fnd[x] = fst[x] , fst[x] = fst[y] + len[i];
else if(fst[y] + len[i] > fnd[x]) fnd[x] = fst[y] + len[i];
}
}
}
void dfs2(int x , int fa)
{
int i , y;
for(i = head[x] ; i ; i = next[i])
{
y = to[i];
if(y != fa)
{
if(fst[x] - len[i] == fst[y]) ff[y] = max(ff[x] + len[i] , fnd[x] + len[i]);
else ff[y] = max(ff[x] + len[i] , fst[x] + len[i]);
dfs2(y , x);
}
}
}
int getsub(int l , int r)
{
int k = log[r - l + 1];
return max(maxn[l][k] , maxn[r - (1 << k) + 1][k]) - min(minn[l][k] , minn[r - (1 << k) + 1][k]);
}
int find(int t)
{
int l = t , r = n , mid , ans;
while(l <= r)
{
mid = (l + r) >> 1;
if(getsub(t , mid) <= k) ans = mid , l = mid + 1;
else r = mid - 1;
}
return ans;
}
int main()
{
int i , j , x , y , ans = -1;
scanf("%d%d" , &n , &k);
for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(i , x , y) , add(x , i , y);
dfs1(1 , 0) , dfs2(1 , 0);
for(i = 1 ; i <= n ; i ++ ) maxn[i][0] = minn[i][0] = max(ff[i] , fst[i]);
for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
for(i = 1 ; i <= log[n] ; i ++ )
for(j = 1 ; j <= n - (1 << i) + 1 ; j ++ )
maxn[j][i] = max(maxn[j][i - 1] , maxn[j + (1 << (i - 1))][i - 1]) , minn[j][i] = min(minn[j][i - 1] , minn[j + (1 << (i - 1))][i - 1]);
for(i = 1 ; i <= n - p + 1 ; i ++ )
x = find(i) , ans = max(ans , find(i) - i + 1);
printf("%d\n" , ans);
return 0;
}

【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分的更多相关文章

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

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

  2. [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案

    考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情.. 先用dfs处理出来每个节点以他为根的子树的最长链和次长链.(后面会用到) 然后用类似dp ...

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

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

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

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

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

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

  6. 重建道路 树形DP

    重建道路 树形DP 给一棵树,问最少断多少边使得这棵树树最终只有\(p​\)个节点 设计dp状态\(f[u][i][j]\)表示节点\(u\),到第\(i\)个儿子,使\(j\)个节点分离,但是不分离 ...

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

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

  8. Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]

    题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...

  9. BZOJ2500: 幸福的道路

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

随机推荐

  1. 一篇RxJava友好的文章(二)

    上一篇文章介绍了rxjava的基本用法,和一些常用的操作符,以及rxjava的链式操作带来的好处.由于rxjava非常的强大,让我如此的痴迷,我打算写五篇文章,专门讲解rxjava 常见的操作符和用法 ...

  2. fastjson 应用

    fastjson优势就是解析快,用法和json-lib.jar差不多(如下图) 贴心的附上jar和反编译工具:https://pan.baidu.com/s/1iADAiFyoUZVBAFSPsIeY ...

  3. 【杂题总汇】HDU多校赛第十场 Videos

    [HDU2018多校赛第十场]Videos 最后一场比赛也结束了…… +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和 ...

  4. git--分布式版本管理系统

    参考博客:廖雪峰的官方网站 一.window安装git Git官网直接下载安装程序,默认选项安装即可. 1.设置自己的git(cmd命令或者git bash进入) git config --globa ...

  5. sql常用函数instr()和substr()

    Decode decode(条件,值1,翻译值1,值2,翻译值2,...,缺省值) 该函数与程序中的 If...else if...else 意义一样 NVL 格式:NVL( string1, rep ...

  6. JZOJ 5906. 传送门

    Description             8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normalgod扔进了一间实验室.这间实 ...

  7. 006---Django静态文件配置

    静态文件:Js.Css.Fonts.Image等 这个不难.在setting.py文件加一行 # 别名 用户在url地址栏输入127.0.0.1:8000/static/文件 可以直接访问static ...

  8. 37-生成 JWT Token

    接到上篇文章 安装扩展插件nuget package方法安装包 使用 ctrl+shift+p打开命令面板 增加这个包,  Microsoft.AspNetCore.Authentication.Jw ...

  9. 笔记-falsk-入门-1

    笔记-falsk-入门-1 1.      前言 有几个概念需要解释下,WSGI,JINJA2,WERKZEUG Flask是典型的微框架,作为Web框架来说,它仅保留了核心功能:请求响应处理和模板渲 ...

  10. java实时监听日志写入kafka(多目录)

    目的 实时监听多个目录下的日志文件,如有新文件切换到新文件,并同步写入kafka,同时记录日志文件的行位置,以应对进程异常退出,能从上次的文件位置开始读取(考虑到效率,这里是每100条记一次,可调整) ...