给定一棵n个点并且有边权的树,每个点的权值为该点能走的最远长度,并输入m个询问,每次询问最多有多少个编号连续的点,他们的最大最小点权差小于等于Q。N<=50000 M<=500 Q<=10000000

  我们知道一个点能走的最远端点一定是树的直径的端点,所以我们只需从树的直径两端点dfs,就可以求出每个点能到的最远长度。。然后rmq+尺取即可。

这道题如果用系统的log会tle,所以必须手打log2。原理会再放一篇博客。

 #include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn=, maxmi=, INF=1e9;
//const double exp=1e-6;
int n, m, cntedge, maxdist, maxdistpos;
int fir[maxn], val[maxn];
int fmaxm[maxn][maxmi], fminm[maxn][maxmi];
struct Edge{
int to, v, next;
};
Edge edge[maxn]; void addedge(int x, int y, int z){
++cntedge;
Edge &nowedge1=edge[cntedge];
nowedge1.to=y, nowedge1.v=z, nowedge1.next=fir[x];
fir[x]=cntedge;
++cntedge;
Edge &nowedge2=edge[cntedge];
nowedge2.to=x, nowedge2.v=z, nowedge2.next=fir[y];
fir[y]=cntedge;
return;
} void dfs(int now, int par, int dist){
int nowedge, nowson;
nowedge=fir[now];
while (nowedge){
nowson=edge[nowedge].to;
if (nowson==par){
nowedge=edge[nowedge].next;
continue;
}
dfs(nowson, now, dist+edge[nowedge].v);
nowedge=edge[nowedge].next;
}
if (dist>val[now]) val[now]=dist;
if (dist>maxdist){
maxdist=dist;
maxdistpos=now;
}
return;
} int flog2(float x) {
return ((unsigned&)x>>&)-;
}
int dvalue(int head, int tail){
int maxm=, minm=1e9;
int lognum=flog2(tail-head+);
maxm=max(fmaxm[head][lognum], fmaxm[tail-(<<lognum)+][lognum]);
minm=min(fminm[head][lognum], fminm[tail-(<<lognum)+][lognum]);
return maxm-minm;
} void init(){
memset(fir, , sizeof(fir));
memset(val, , sizeof(val));
for (int i=; i<maxn; ++i){
edge[i].next=edge[i].to=edge[i].v=;
}
cntedge=;
} int ri(){
char c;
int flag=, r=;
do{
c=getchar();
if (c=='-') flag=-;
} while (!isgraph(c));
do{
r=r*+c-;
c=getchar();
} while (isgraph(c));
return r*flag;
} int main(){
int x, y, z;
while (~scanf("%d%d", &n, &m)){
if (n==&&m==) break;
init();
for (int i=; i<n; ++i){
x=ri(), y=ri(), z=ri();
addedge(x, y, z);
}
int s=, far1, far2;
maxdist=, dfs(s, , );
far1=maxdistpos;
maxdist=, dfs(far1, , );
far2=maxdistpos;
maxdist=, dfs(far2, , );
//for (int i=1; i<=n; ++i)
//printf("%d\n", val[i]);
int q=;
for (int i=; i<=n; ++i)
fmaxm[i][]=fminm[i][]=val[i];
for (int i=; i<maxmi; ++i){
for (int j=; j<=n-(<<i)+; ++j){
fmaxm[j][i]=max(fmaxm[j][i-], fmaxm[j+(<<(i-))][i-]);
fminm[j][i]=min(fminm[j][i-], fminm[j+(<<(i-))][i-]);
}
}
int h=, t=, maxm=;
for (int i=; i<m; ++i){
q=ri();
h=, t=, maxm=;
while (t<=n){
if (dvalue(h, t)<=q) ++t;
else ++h;
if ((t-h)>maxm) maxm=t-h;
}
printf("%d\n", maxm);
}
}
return ;
}

树的直径+rmq+(伪)单调队列 -HDU4123的更多相关文章

  1. 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列

    题目描述 给出一棵树,定义一个点到一条路径的距离为这个点到这条路径上所有点的距离的最小值.求一条长度不超过s的路径,使得所有点到这条路径的距离的最大值最小. 输入 包含n行: 第1行,两个正整数n和s ...

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

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

  3. 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)

    题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...

  4. HDU - 5289 Assignment (RMQ+二分)(单调队列)

    题目链接: Assignment  题意: 给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k. 题解: RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相 ...

  5. 求最长的任意两元素差不超过M的子段——双指针+单调队列hdu4123

    换根dp的部分比较容易,难点在于求求最长的任意两元素差不超过M的子段 首先会想到双指针维护(尺取法),如果p1,p2间的max-min>M,那么p1向右移动,直到p1,p2间的max-min&g ...

  6. 洛谷 P2216 [HAOI2007]理想的正方形 || 二维RMQ的单调队列

    题目 这个题的算法核心就是求出以i,j为左上角,边长为n的矩阵中最小值和最大值.最小和最大值的求法类似. 单调队列做法: 以最小值为例: q1[i][j]表示第i行上,从j列开始的n列的最小值.$q1 ...

  7. 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 ...

  8. 【HDU6701】Make Rounddog Happy【权值线段树+双向单调队列】

    题意:给你一个序列,求满足要求的子序列个数,其中要求为: 1.子序列的max-子序列长度len<=k 2.子序列中不出现重复的数字 题解:首先看到子序列max,很容易想到枚举最大值然后分治,这个 ...

  9. cf1208 E Let Them Slide(差分+RMQ\单调队列)

    题意 如题目的图所示,每行都可以左右移动,但是数字不允许断开,且不许越界(宽度为w). 单独求每一列的最大的和为多少. 思路 对于每一列来说,在每一行上都有一个可以取到的区间, 所以,对于一列来说,答 ...

随机推荐

  1. java_面试_01_一个月的面试总结(java)

    重点知识 由于我面试的JAVA开发工程师,针对于JAVA,需要理解的重点内容有: JVM内存管理机制和垃圾回收机制(基本每次面试都会问,一定要搞得透彻) JVM内存调优(了解是怎么回事,一般做项目过程 ...

  2. 绘图工具--turtle模块

    turtle模块主要使用两个类,一个是TurtleScreen类,表示画布(窗口),用来展示画的位置:一个是Turtle类,用来充当画笔,用来画. 两个类的方法也以同名的函数的形式存在,所以可以以面向 ...

  3. bzoj1208Splay

    Splay查前驱后继 小tips:在bzoj上while(scanf)这种东西可以让程序多组数据一起跑 反正没加我就t了 #include<cstdio> #include<iost ...

  4. 装了Ironpython还需要装Python吗?

    IronPython 是一种在 NET 和 Mono 上实现的 Python 语言,由 Jim Hugunin(同时也是 Jython 创造者)所创造.IronPython是优雅的python编程语言 ...

  5. android使用wcf接收上传图片视频文件

    一.Android 权限配置文件: <?xml version="1.0" encoding="utf-8"?> <manifest xmln ...

  6. linux下dns设置详解

    DNS就是Domain Name System,它能够把形如www.21php.com这样的域名转换为211.152.50.35这样的IP地址;没有DNS,浏览21php.com这个网站时,就必须用2 ...

  7. MyEclipse 手动安装Velocity 编辑器

    最近项目有使用Velocity 模板引擎,从而会用到*.VM页面!Myeclipse打开VM页面字体一片漆黑,哪有JSP那样看起来舒服(个人感觉)!为了解决这一问题就要安装Velocity编辑器,安装 ...

  8. go语言执行windows下命令行的方法

    转自:http://www.jb51.net/article/61727.htm 在golang里执行windows下的命令行,例如在golang里面调用 del d:\a.txt 命令 packag ...

  9. CUDA V9.2 sample编译问题

    这个哥们也遇到一样的问题 CUDA 9.1/9.2 与 Visual Studio 2017 (VS2017 15.6.4) 的不兼容问题 错误有显示 #if _MSC_VER < 1600 | ...

  10. Android精品资源汇总,10个源码(持续更新)

    最近一直在学习Android,在各大社区逛,总结下自己看到的一些不错的源码.希望可以给大家带来帮助. 1.Android精品源码:带动态效果的Button(按钮) 最喜欢各种效果的按钮了,没办法就是这 ...