题意:

给定n个点的带边权树Q个询问。

以下n-1行给出树

以下Q行每行一个数字表示询问。

首先求出dp[N] :dp[i]表示i点距离树上最远点的距离

询问u, 表示求出 dp 数组中最长的连续序列使得序列中最大值-最小值 <= u,输出这个序列的长度。

思路:

求dp数组就是求个树的直径然后dfs一下。

对于每一个询问,能够用一个单调队列维护一下。O(n)的回答。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if(x>9) pt(x/10);
putchar(x%10+'0');
}
typedef long long ll;
const int N = 50010;
int n, Q;
struct Edge{
int to, nex; ll dis;
}edge[N<<1];
struct node {
int v, id;
node() {}
node(int _id, int _v) {
id = _id; v = _v;
}
};
int head[N], edgenum;
void init(){for(int i = 1; i <= n; i++)head[i] = -1; edgenum = 0;}
void add(int u, int v, ll d){
Edge E = {v, head[u], d};
edge[edgenum] = E;
head[u] = edgenum++;
}
ll dis[N], dp[N], len;
int Stack[N], top, pre[N], vis[N];
int BFS(int x){
for(int i = 1; i <= n; i++)
dis[i] = -1;
dis[x] = 0; pre[x] = -1;
int far = x;
queue<int> q; q.push(x);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to;
if(dis[v] == -1)
{
dis[v] = dis[u] + edge[i].dis;
pre[v] = u;
if(dis[far] < dis[v])
far = v;
q.push(v);
}
}
}
return far;
}
void dfs(int u){
vis[u] = 1;
for(int i = head[u]; ~i; i = edge[i].nex)
{
int v = edge[i].to;
if(vis[v])continue;
dp[v] = dp[u] + edge[i].dis;
dfs(v);
}
}
void build(){//预处理树的直径
int E = BFS(1);
int S = BFS(E);
top = 0;
int u = S;
len = dis[S];
for(int i = 1; i <= n; i++) vis[i] = 0;
while(u!=-1)
{
Stack[top++] = u;
dp[u] = max(dis[u], len - dis[u]);
vis[u] = 1;
u = pre[u];
}
for(int i = 0; i < top; i++) dfs(Stack[i]);
}
void input(){
init(); ll d;
for(int i = 1, u, v; i < n; i++)
{
rd(u); rd(v); rd(d);
add(u, v, d); add(v, u, d);
}
} node mx[N], mi[N];
int h1, t1, h2, t2;
int main() {
int v, idx, ans;
while(cin>>n>>Q, n+Q) {
input();
build();
while(Q--)
{
rd(v);
ans = h1 = t1 = h2 = t2 = 0;
idx = 1;
for (int i = 1; i <= n; ++i) {
while (h1!=t1 && mx[t1-1].v <= dp[i])
-- t1;
mx[t1++] = node(i, dp[i]);
while (h2!=t2 && mi[t2-1].v >= dp[i])
-- t2;
mi[t2++] = node(i, dp[i]);
while (h1!=t1&&h2!=t2) {
if (mx[h1].v-mi[h2].v>v)
++ idx;
else
break;
while (h1!=t1&&mx[h1].id<idx)
++h1;
while (h2!=t2&&mi[h2].id<idx)
++h2;
}
ans = max(ans, i-idx+1);
}
pt(ans);
putchar('\n');
}
}
return 0;
}

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

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

  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. POJ 3162 Walking Race(树的直径+单调队列)

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

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

  5. HDU 4123 Bob's Race:树的直径 + 单调队列 + st表

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[ ...

  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. EHCache的使用

    在开发高并发量,高性能的网站应用系统时,缓存Cache起到了非常重要的作用.本文主要介绍EHCache的使用,以及使用EHCache的实践经验.笔者使用过多种基于Java的开源Cache组件,其中包括 ...

  2. nyoj 117 找到的倒数 【树阵】+【分离】

    这个问题的解决方案是真的很不错!!! 思路:建立一个结构体包括val和id. val就是输入的数,id表示输入的顺序.然后依照val从小到大排序.假设val相等.那么就依照id排序. 假设没有逆序的话 ...

  3. LeetCode: Multiply Strings. Java

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  4. REST API 基于ACCESS TOKEN

    REST API 基于ACCESS TOKEN 的权限解决方案   REST 设计原则是statelessness的,而且但客户端是APP时,从APP发起的请求,不是基于bowers,无法带相同的se ...

  5. Android源码文件夹结构

    Android 2.2 |-- Makefile |-- bionic               (bionic C库) |-- bootable            (启动引导相关代码) |-- ...

  6. defgen工具

    构造defgen档 由于 Oracle 和 SQL Server 中的数据类型不同.所以您必须建立数据类型转换.GoldenGate 提供了一个名为 DEFGEN 的专用工具.用于生成数据定义,当源表 ...

  7. 使用 WPF 实现所见即所得HTML编辑器

    Introduction In this tip, you will learn the use of WPF webbrowser control and the use of the librar ...

  8. MongoDB时间处理问题

    MongoDB保存到数据库的时候,默认为UTC时间,在数据库保存时,会和当前时间有个间隔,差距为8小时. 在读取的时候,需要再次转换回来,比较麻烦. 其实,Mongo本身就已经提供了相应的处理方法,即 ...

  9. 【JAVA】【NIO】3、Java NIO Channel

    Java NIO和流量相似,但有些差异: ·通道可读写,流仅支持单向.读或写 ·异步通道读取 ·通道读写器,他们是和Buffer交替 道的实现 下面是Java NIO中最重要的通道的实现: ·File ...

  10. JDK5什么是新的堵塞队列线程(四)

    一. 堵塞队列与普通队列: 队列是一种主要的数据类型,其典型特征是先进先出. 堵塞队列和普通队列的差别在于: 当队列为空时.从队列中获取元素的线程会被堵塞.直到其它的线程往空的队列里插入新的元素: 当 ...