题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123

参考博客:两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race - cc_again的专栏 - CSDN博客  https://blog.csdn.net/cc_again/article/details/12011757

题意:给出一棵有n个点的树,每条树边都有一个权值,对于每一个点,它都有一个编号,我们取它到其他点的最大距离记录下来,现在q个询问,每个询问会给出一个k,我们要找到最长的一段点的编号是连续的区间,满足这段区间里面的点到其他点的最大距离  的最大值减去这段区间里面点到其他区间的最大值 里面的最小值 的差值小于等于k,输出这段区间的长度。

思路:首先我们要求出这棵树上面的每一个点到其他点的最大距离,所以我们进行两次记忆化搜索(两次DFS),第一次DFS我们挑一个点为根节点(假设为1)往下搜索每一颗子树的根节点到它的儿子节点距离的最大值和次大值(次大值是为了等下求一个点到它的非子树节点的最大距离),然后进行第二次DFS(还是从1开始),向下搜索找每个点到它的非子树节点的最大距离。这样我们最后把两个最大值比较就可以得到这颗树上的每一个点到其他点的最大距离。

每一次我们要查询的就是一段连续区间里面的最大值减去最小值,看这个值是否小于k,因为查询次数很多,所以我们可以用RMQ来进行预处理,先计算出所有区间里面的最大值和最小值,最后用尺取法来枚举区间边界,同时用预处理好了的值进行判断,来找出最大区间长度。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<vector>
#include<set>
#include<cstdio>
#include<string>
#include<deque>
using namespace std;
typedef long long LL;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define maxn 50005
int maxx[maxn][],minn[maxn][],mx1[maxn],mx2[maxn],f[maxn];
//maxx存区间最大值,minn...,mx1[i]存点i到其他点的最大距离,mx2[i]存次大距离
//f[i]存点i到非子树节点的最大距离
int n,m,t,cnt,ans;
int head[maxn];
bool vis[maxn];
struct node{
int v,w,next;
}edge[maxn<<];
void init(){
memset(head,-,sizeof(head));
cnt=;
memset(mx1,,sizeof(mx1));
memset(mx2,,sizeof(mx2));
memset(f,,sizeof(f));
}
void add(int u,int v,int w){
edge[++cnt].v=v;
edge[cnt].next=head[u];
edge[cnt].w=w;
head[u]=cnt;
}
void DFS(int u){//找点u到子树节点里面的最大距离和次大距离
vis[u]=true;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(!vis[v]){
DFS(v);
mx2[u]=max(mx1[v]+w,mx2[u]);
if(mx2[u]>mx1[u]) swap(mx2[u],mx1[u]);
}
} }
void DFS1(int u){//找点u到非子树节点的最大距离
vis[u]=true;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].v;
int w=edge[i].w;
if(!vis[v]){
f[v]=max(f[v],f[u]+w);
if(mx1[u]==w+mx1[v])
f[v]=max(f[v],w+mx2[u]);
else
f[v]=max(f[v],w+mx1[u]);
DFS1(v);
}
}
}
void RMQ_init(){//RMQ预处理
for(int i=;i<=n;i++)
maxx[i][]=minn[i][]=max(f[i],mx1[i]);
for(int j=;(<<j)<=n;j++){
for(int i=;i+(<<j)-<=n;i++){
maxx[i][j]=max(maxx[i][j-],maxx[i+(<<(j-))][j-]);
minn[i][j]=min(minn[i][j-],minn[i+(<<(j-))][j-]);
}
}
}
int cal(int l,int r){//返回区间[l,r]的最大值减最小值的值
int k=;
while((<<(k+))<=r-l+)
k++;
return max(maxx[l][k],maxx[r-(<<k)+][k])-min(minn[l][k],minn[r-(<<k)+][k]);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
if(!n||!m)
break;
init();
int u,v,w;
for(int i=;i<=n-;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
memset(vis,false,sizeof(vis));
DFS();
memset(vis,false,sizeof(vis));
DFS1();
RMQ_init();
int k;
while(m--){
scanf("%d",&k);
int l=,r=;
ans=;
while((l<n||r<n)&&l<=r){//尺取法枚举区间
while(r<n&&cal(l,r)<=k){
ans=max(ans,r-l+);
r++;
}
if(r==n&&cal(l,r)<=k){
ans=max(ans,r-l+);
break;
}
l++;
}
printf("%d\n",ans);
} }
return ;
}

树形DP+RMQ+尺取法 hdu4123的更多相关文章

  1. hdu4123-Bob’s Race(树形dp+rmq+尺取)

    题意:Bob想要开一个运动会,有n个房子和n-1条路(一棵树),Bob希望每个人都从不同的房子开始跑,要求跑的尽可能远,而且每条路只能走最多一次.Bob希望所有人跑的距离的极差不大于q,如果起点的编号 ...

  2. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  3. HDU-4123-树形dp+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. csu 1553(RMQ+尺取法)

    1553: Good subsequence Time Limit: 2 Sec  Memory Limit: 256 MBSubmit: 794  Solved: 287[Submit][Statu ...

  5. 树形DP+RMQ+单调队列(Bob’s Race HDU4123)

    题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q, ...

  6. hdu 4123--Bob’s Race(树形DP+RMQ)

    题目链接 Problem Description Bob wants to hold a race to encourage people to do sports. He has got troub ...

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

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

  8. HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)

    题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度. 做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP ...

  9. POJ3162 Walking Race(树形DP+尺取法+单调队列)

    题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长. 各个结点到其他结点的最远距离可以用树形DP ...

随机推荐

  1. kubernetes安装过程报错及解决方法

    1.your configuration file uses an old API spec: "kubeadm.k8s.io/v1alpha2". 执行kubeadm init ...

  2. C# 中的 ConfigurationManager类引用方法

    c#添加了Configuration;后,竟然找不到 ConfigurationManager 这个类,后来才发现:虽然引用了using System.Configuration;这个包,但是还是不行 ...

  3. Shell 编程 (变量和条件测试)

    变量: 1 . 变量声明 直接使用变量 + 赋值 #!/bin/bash NAME='HELLO WORD' echo $NAME 使用 declare 关键字声明 declare(选项)(参数) + ...

  4. Mysql 索引 n-gram分词引擎使用

    概述: 类似于书籍的目录,找到一本书的特定内容,需要首先找到内容对应页码,定位对应页码 存储引擎使用类似方法进行数据查找,先找到索引中对应值,然后根据匹配的索引找到对应行 实现原理: 索引的实现通常使 ...

  5. QtCreator中F1帮助不能使用的解决方法

    环境:ubuntu11.04 在Qt中按F1跳转帮助是一个很方便的东东,点击左边的Help图标也是一样的功能.我今天遇到的问题是F1跳转出错,找不到文档: “No documentation avai ...

  6. Mycat 水平拆分

    一致性Hash理解 https://blog.csdn.net/cywosp/article/details/23397179?utm_source=blogxgwz1 十种 水平拆分 https:/ ...

  7. Mongo 应用查询

    官网操作手册,基本就够用 https://docs.mongodb.com/manual/ 下面是个分组查询的例子,项目中用到然后查了个例子,自己理解了下,觉得很好很强大. https://blog. ...

  8. 批量杀死多个进程 linux kill

    批量杀进程 -| “grep -v grep”是在列出的进程中去除含有关键字“grep”的进程. “cut -c 9-15”是截取输入行的第9个字符到第15个字符,而这正好是进程号PID,也有使用aw ...

  9. mycat 单库分表

    上次把mycat的读写分离搞定了,这次试下单库分表,顾名思义就是在一个库里把一个表拆分为多个 需要配置的配置文件为 schema.xml 配置内容如下 <!DOCTYPE mycat:schem ...

  10. Node稳定性的研究心得

    目前大部分Web服务器,如Apache,都使用多线程的方式响应多用户请求,即一个线程服务一个用户请求.这种模式其中一个好处是,当某个请求的线程上抛出的异常没被捕获,只会影响当前这个线程,不会影响其他请 ...