给定一棵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. elasticsearch的store属性跟_source字段——如果你的文档长度很长,存储了_source,从_source中获取field的代价很大,你可以显式的将某些field的store属性设置为yes,否则设置为no

    转自:http://kangrui.iteye.com/blog/2262860 众所周知_source字段存储的是索引的原始内容,那store属性的设置是为何呢?es为什么要把store的默认取值设 ...

  2. SWFObject是什么

    一:简介: SWFObject是一个用于在HTML中方便插入Adobe Flash媒体资源(*.swf文件)的独立.敏捷的JavaScript模块.该模块中的JavaScript脚本能够自动检测PC. ...

  3. (转)python调取C/C++的dll生成方法

    本文针对Windows平台下,python调取C/C++的dll文件. 1.如果使用C语言,代码如下,文件名为test.c. __declspec(dllexport) int sum(int a,i ...

  4. redis的read error on connection错误解决

    昨日,公司php调用redis报错:read error on connection 2015-01-29 23:59:050.13330000,redis存放的是用户session. 在网上查询,大 ...

  5. Python:.join()函数

    转于:https://blog.csdn.net/chixujohnny/article/details/53301995 博主:chixujohnny 介绍:.join是一个字符串操作函数,将元素相 ...

  6. 【转】 Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner

    目录(?)[-] GridView Spinner GridView GridView是网格状布局,如图所示.在了解ListView后,很容易了解GridView.下面是例子的XML文件. <? ...

  7. Scala总结

    Scala总结 ===概述 scala是一门以Java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言. scala是纯粹的面向对象的语言.java虽然是面 ...

  8. Python-RabbitMQ消息队列的发布与订阅

    RabbitMQ消息队列的发布与订阅类似于广播,一端发送消息,多个客户端可以同时接收到消息 fanout:所有绑定到exchange的queue都可以接收消息 消息发布端 # -*- coding:u ...

  9. 快速搭建SpringBoot项目

    Spring Boot简介: Spring Boot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目.它使用习惯优于配置的理念让你的项目快速运行起来,使用Spring Bo ...

  10. 【java并发编程艺术学习】(一)初衷、感想与笔记目录

    不忘初心,方得始终. 学习java编程这么长时间,自认为在项目功能需求开发中没啥问题,但是之前的几次面试和跟一些勤奋的或者小牛.大牛级别的人的接触中,才发现自己的无知与浅薄. 学习总得有个方向吧,现阶 ...