题目链接: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. qtav----ffmeg在ubuntu和win10上的编译和运行

    最近在windows上和ubuntu上都安装了qtav并且通过了编译测试,实测播放中英文的视频文件功能正常,有图像有声音. 大致情况是,操作系统ubuntu: wkr@sea-X550JK:~$ ca ...

  2. android常用权限

    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permiss ...

  3. Java之StringBuffer和StringBuilder的差别与联系

    2.StringBuilder,StringBuffer 字符串拼接时用这两个类,效率高.节约内存.假设用字符串 "+"号拼接 性能差.而且浪费空间,产生非常多垃圾 StringB ...

  4. android:分享 一个非常强大的LOG开关---Log.isLoggable

    1.API亮点: 此API能够实现不更换APK.在出问题的手机上就直接能抓到有效log,能提升不少工作效率. .API介绍 近期在解决短信问题时.看到一个非常强大的LOG开关---Log.isLogg ...

  5. IE hack 条件语句

    只在固定IE版本下执行 将以下代码放在head标签中,在script标签中写js即可 <!--[if IE 8]> <script> console.log("in ...

  6. 模拟多级复选框效果--jquery

    今天又次体会到jquery的强大了,做了个多级复选框的效果,代码总共就20+行就over了. 我又想用js来做一个看看,才写了几个方法就写不动了,兼容性要考虑很多,而且代码量直线上升. 主要分享下jq ...

  7. httpClient实现

    1.实现功能 向关注了微信公众号的微信用户群发消息.(可以是所有的用户,也可以是提供了微信openid的微信用户集合) 2.基本步骤 前提: 已经有认证的公众号或者测试公众账号 发送消息步骤: 发送一 ...

  8. COM线程模型 套间概念

    COM线程模型 套间概念 1) 单线程套间.线程是COM主线程,初始化COM库的进程的第一个线程.即使从其他线程访问COM组件,也不需要手工同步,COM库已经实现了同步.寓所线程里有个消息处理循环来处 ...

  9. Pycharm context menu disable RUN option

    这个问题很坑.正常来说一个文件右键出来的是 Run 选项, 可是近期几个文件都是 Unititest 的測试选项,每次要执行的时候都要手工去配置Run Option,在尝试了: 0. 重置IDE配置 ...

  10. 滑动窗口计数java实现

    滑动窗口计数有很多使用场景,比如说限流防止系统雪崩.相比计数实现,滑动窗口实现会更加平滑,能自动消除毛刺. 概念上可以参考TCP的滑窗算法,可以看一下这篇文章(http://go12345.iteye ...