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

题意:

  给你一棵树,n个节点,每条边有长度。

  然后有m个询问,每个询问给定一个q值。

  设dis[i]为:从节点i出发,不重复经过节点,所能够走的最远距离。

  每次询问问你:区间[l,r]最长能有多长,同时保证 max{dis[i]} - min{dis[i]} <= q (i∈[l,r])

题解:

  首先有一个结论:

    从树上的任意一个节点出发,尽可能往远走,最终一定会到达树的直径的两个端点之一。

  所以先两遍dfs1,找出直径的两个端点。

  然后分别从两个端点dfs2,求出所有节点的dis[i]。

  因为节点必须选编号连续的一段区间,所以可以用到单调队列。

  枚举每个节点i加入队首。

  然后对于每个i,不断地丢掉队尾pos++,直到当前的区间[pos,i]符合条件。

  那么每次都需要判断是否有 max{dis[i]} - min{dis[i]} <= q (i∈[pos,i])

  这就要用到st表了,然后O(1)判断就好。

AC Code:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define MAX_N 50005
#define MAX_K 20 using namespace std; struct Edge
{
int dest;
int len;
Edge(int _dest,int _len)
{
dest=_dest;
len=_len;
}
Edge(){}
}; int n,m;
int maxd;
int st,ed;
int dis[MAX_N];
int lg[MAX_N];
int maxt[MAX_N][MAX_K];
int mint[MAX_N][MAX_K];
vector<Edge> edge[MAX_N]; void read()
{
for(int i=;i<=n;i++) edge[i].clear();
int x,y,z;
for(int i=;i<n;i++)
{
cin>>x>>y>>z;
edge[x].push_back(Edge(y,z));
edge[y].push_back(Edge(x,z));
}
} void dfs1(int now,int p,int d,int &v)
{
if(d>maxd)
{
maxd=d;
v=now;
}
for(int i=;i<edge[now].size();i++)
{
Edge temp=edge[now][i];
if(temp.dest!=p) dfs1(temp.dest,now,d+temp.len,v);
}
} void dfs2(int now,int p,int d)
{
dis[now]=max(dis[now],d);
for(int i=;i<edge[now].size();i++)
{
Edge temp=edge[now][i];
if(temp.dest!=p) dfs2(temp.dest,now,d+temp.len);
}
} void init_st()
{
lg[]=-;
for(int i=;i<=n;i++)
{
lg[i]=lg[i>>]+;
maxt[i][]=mint[i][]=dis[i];
}
for(int k=;(<<k)<=n;k++)
{
for(int i=;i+(<<k)-<=n;i++)
{
maxt[i][k]=max(maxt[i][k-],maxt[i+(<<(k-))][k-]);
mint[i][k]=min(mint[i][k-],mint[i+(<<(k-))][k-]);
}
}
} int query_max(int l,int r)
{
int k=lg[r-l+];
return max(maxt[l][k],maxt[r-(<<k)+][k]);
} int query_min(int l,int r)
{
int k=lg[r-l+];
return min(mint[l][k],mint[r-(<<k)+][k]);
} void work()
{
maxd=-;
dfs1(,-,,st);
maxd=-;
dfs1(st,-,,ed);
memset(dis,-,sizeof(dis));
dfs2(st,-,);
dfs2(ed,-,);
init_st();
while(m--)
{
int q;
cin>>q;
int ans=;
int pos=;
for(int i=;i<=n;i++)
{
while(query_max(pos,i)-query_min(pos,i)>q) pos++;
ans=max(ans,i-pos+);
}
cout<<ans<<endl;
}
} int main()
{
while(cin>>n>>m)
{
if(n== && m==) break;
read();
work();
}
}

HDU 4123 Bob's Race:树的直径 + 单调队列 + st表的更多相关文章

  1. HDU 4123 Bob’s Race 树的直径+单调队列

    题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...

  2. HDU 4123 Bob’s Race 树的直径 RMQ

    Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=41 ...

  3. hdu 4123 Bob’s Race 树的直径+rmq+尺取

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

  4. POJ 3162 Walking Race(树的直径+单调队列)

    题目大意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到dis[1],dis[2],dis[3]……dis[n] ,在数列的dis中求一个最长的 ...

  5. HDU 4123 Bob’s Race 树的直径+ST表

    Bob’s Race Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=41 ...

  6. HDU 4123 Bob’s Race 树形dp+单调队列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...

  7. hdu 4123 Bob’s Race (dfs树上最远距离+RMQ)

    C - Bob’s Race Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Subm ...

  8. HDU 4123(树的直径+单调队列)

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

  9. HDU 4123 Bob’s Race(树形DP,rmq)

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

随机推荐

  1. u3D大场景的优化

    首先介绍下draw call(这个东西越少你的游戏跑的越快): 在游戏中每一个被展示的独立的部分都被放在了一个特别的包中,我们称之为“描绘指令”(draw call),然后这个包传递到3D部分在屏幕上 ...

  2. POJ 1654 area 解题

    Description You are going to compute the area of a special kind of polygon. One vertex of the polygo ...

  3. Shell Error: -bash: ./test.sh: /bin/bash^M: bad interpreter: No such file or directory (转)

    错误原因可能有以下几种: 1.在WIN底下用文本编辑工具修改过参数变量,在保存的时候没注意编码格式造成的, 2.也有可能是在VIM里修改,第一行末尾按到ctrl_v 查看文件是DOS格式.UNIX格式 ...

  4. 创建一个动态Web项目:

    开始你的Eclipse,然后进入“文件”>“新建”>“动态Web项目,然后输入项目名称为HelloWorldStruts2和设置其他的选项,在下面的屏幕: 选择在屏幕上的所有默认选项,最后 ...

  5. centos7.0 增加/usr分区的容量减少home分区的大小

    把/home内容备份,然后将/home文件系统所在的逻辑卷删除,扩大/root文件系统,新建/home:tar cvf /tmp/home.tar /home #备份/homeumount /home ...

  6. python 之前函数补充(__del__, item系列, __hash__, __eq__) , 以及模块初体验

    __str__ :  str(obj) ,  需求必须实现了 __str__, 要求这个方法的返回值必须是字符串  str  类型 __repr__ (意为原型输出):  是 __str__ 的备胎( ...

  7. 软件测试人员需要精通的开发语言(3)--- Linux

    Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.不得不说下,中国产的红旗系统,牛的一逼,造价很贵,但具体何用处估 ...

  8. 【BZOJ3563/3569】DZY Loves Chinese II 线性基神题

    [BZOJ3563/3569]DZY Loves Chinese II Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以 ...

  9. 【BZOJ4320】ShangHai2006 Homework 分段+并查集

    [BZOJ4320]ShangHai2006 Homework Description   1:在人物集合 S 中加入一个新的程序员,其代号为 X,保证 X 在当前集合中不存在.    2:在当前的人 ...

  10. css 坑记

    1. div 内容超出 (做换行处理)   要注意 white-space属性的运用 设置 div width:100%;(或者固定值) 设置换行  word-break: break-all; 设置 ...