【BZOJ2282】[Sdoi2011]消防

Description

某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000)。
这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的行业是消防业。由于政府对国民的热情忍无可忍(大量的消防经费开销)可是却又无可奈何(总统竞选的国民支持率),所以只能想尽方法提高消防能力。
现在这个国家的经费足以在一条边长度和不超过s的路径(两端都是城市)上建立消防枢纽,为了尽量提高枢纽的利用率,要求其他所有城市到这条路径的距离的最大值最小。
你受命监管这个项目,你当然需要知道应该把枢纽建立在什么位置上。

Input

输入包含n行:
第1行,两个正整数n和s,中间用一个空格隔开。其中n为城市的个数,s为路径长度的上界。设结点编号以此为1,2,……,n。
从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。

Output

输出包含一个非负整数,即所有城市到选择的路径的最大值,当然这个最大值必须是所有方案中最小的。

Sample Input

【样例输入1】
5 2
1 2 5
2 3 2
2 4 4
2 5 3

【样例输入2】
8 6
1 3 2
2 3 2
3 4 6
4 5 3
4 6 4
4 7 2
7 8 3

Sample Output

【样例输出1】

5
【样例输出2】

5

HINT

对于100%的数据,n<=300000,边长小等于1000。

题解:首先,选出的路径一定在某条直径上(可以用反证法证明)。

然后我们将直径拎出来,假设我们最后选定的是直径上的[l,r]这部分,那么距离的最大值就是:

max(直径的左端点到l的距离,直径的右端点到r的距离,[l,r]中每个节点的子树(不包含直径的部分)中到该节点最远的距离)

前两个很好求,第三个怎么办?可以先预处理出每个点的子树中最远的距离,然后用单调队列查询最大值。然后就可以用双指针法来确定[l,r]了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=300010;
int n,m,cnt,len,r1,r2,h,t,ans;
int to[maxn<<1],next[maxn<<1],head[maxn],val[maxn<<1],fa[maxn],p[maxn],vis[maxn],f[maxn],dep[maxn],q[maxn],v[maxn];
void dfs(int x)
{
if(dep[x]>dep[r2]) r2=x;
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]) fa[to[i]]=x,dep[to[i]]=dep[x]+val[i],dfs(to[i]);
}
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
int getv(int x)
{
int tmp=dep[x];
for(int i=head[x];i!=-1;i=next[i]) if(!vis[to[i]]&&to[i]!=fa[x]) tmp=max(tmp,getv(to[i]));
return tmp;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd();
int i,j,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
r2=1,dfs(1);
memset(dep,0,sizeof(dep)),memset(fa,0,sizeof(fa));
r1=r2,dfs(r1);
for(a=r2;a;p[++len]=a,vis[a]=1,a=fa[a]);
for(i=1;i<=len;i++) v[i]=getv(p[i])-dep[p[i]];
h=1,t=0,ans=1<<30;
for(i=j=1;i<=len;i++)
{
for(;j<i&&dep[p[j]]-dep[p[i]]>m;j++);
while(h<=t&&v[q[t]]<=v[i]) t--;
q[++t]=i;
while(h<=t&&q[h]<j) h++;
ans=min(ans,max(max(dep[p[i]]-dep[p[len]],dep[p[1]]-dep[p[j]]),v[q[h]]));
}
printf("%d",ans);
return 0;
}

【BZOJ2282】[Sdoi2011]消防 树形DP+双指针法+单调队列的更多相关文章

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

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

  2. POJ3162 Walking Race(树形DP+尺取法+单调队列)

    题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长. 各个结点到其他结点的最远距离可以用树形DP ...

  3. luogu 2491 [SDOI2011]消防 / 1099 树网的核 单调队列 + 树上问题

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 300001 #define inf 1000000000 ...

  4. BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP/后缀数组 单调栈)

    题目链接 \(Description\) \(Solution\) len(Ti)+len(Tj)可以直接算出来,每个小于n的长度会被计算n-1次. \[\sum_{i=1}^n\sum_{j=i+1 ...

  5. 洛谷P2569 股票交易【dp】【单调队列】

    题目描述 最近 \text{lxhgww}lxhgww 又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,\text{lxhgww}lxhgww 预测到了 ...

  6. Codeforces Round #278 (Div. 1) B - Strip dp+st表+单调队列

    B - Strip 思路:简单dp,用st表+单调队列维护一下. #include<bits/stdc++.h> #define LL long long #define fi first ...

  7. 【神仙DP】【单调队列】【模拟题】区间覆盖

    传送门 Description 给出数轴上的n个线段,保留最多k条线段,问这些被保留下来的线段的并集长度为最多为多少. Input 第一行两个数n和k 接下来n行,每行两个数,表示一条线段的左右端点. ...

  8. 【DP】【单调队列】【NOI2005】瑰丽华尔兹

    340. [NOI2005] 瑰丽华尔兹 ★★★ 输入文件:adv1900.in 输出文件:adv1900.out 简单对照 时间限制:1 s 内存限制:128 MB [任务描写叙述] 你跳过华尔兹吗 ...

  9. [DP浅析]线性DP初步 - 2 - 单调队列优化

    目录 #0.0 前置知识 #1.0 简单介绍 #1.1 本质 & 适用范围 #1.2 适用方程 & 条件 #2.0 例题讲解 #2.1 P3572 [POI2014]PTA-Littl ...

随机推荐

  1. EasyBoot使用方法

    1 修改背景图片直接替换掉EasyBoot\disk1\ezboot目录下面的BACK.BMP文件即可.但是限于DOS功能限制,只能使用640×480像素,256位色的BMP图片.   2 鼠标左键单 ...

  2. Linux学习笔记 (四)归档和压缩

    一.zip压缩命令: 1.压缩文件: 格式:zip 压缩文件 源文件 例:zip abc.zip abc  //将abc文件压缩到abc.zip文件内. 2.压缩目录: 格式:zip –r 压缩目录 ...

  3. JSON.parse 的用法,在js中用的。也是反序列化用法。

    参数 text 必需. 一个有效的 JSON 字符串. reviver 可选. 一个转换结果的函数. 将为对象的每个成员调用此函数. 如果成员包含嵌套对象,则先于父对象转换嵌套对象. 对于每个成员,会 ...

  4. [1-4] 把时间当做朋友(李笑来)Chapter 4 【开拓我们的心智】 摘录

    1. 获得知识的基本途径  所有的人获取知识的最为基础的手段就是“体验”. 比“体验”再高级一点的获取知识的手段,就是“试错”(Trial and Error). 在“试错”这个手段的基础上,另外一个 ...

  5. 【MyBatis学习03】原始dao开发方法及其弊端

    上一篇博文总结了一下mybatis的入门,接下来就要开发dao方法了,这篇博文主要总结一下mybatis中原始dao开发的方法,最后并总结一下原始dao开发方法的弊端.mybatis中dao开发应该使 ...

  6. linux系统日志报错

    使用journalctl -xe命令时报错: Error was encountered while opening journal files: Input/output error 日志文件损坏了 ...

  7. mysql select *... where id in (select 字符串 from ... )查询结果问题?

    SQL中的写法为 ); 查询结果为: id TypeName 1 新手 2 手机 在MYSQL中 ); 查询结果为: id TypeName 1 新手 少了一条数据. 其中 查询结果为 Newcard ...

  8. Redis之最大内存置换策略

    0.前言 Redis默认最大内存大小是应用程序可访问的内存大小, 32位windows下是2GB, linux下是3GB. 64位下可以访问的内存为2^64字节, Redis提供了maxmemory字 ...

  9. Atitit.研发管理---api版本号策略与版本控制

    Atitit.研发管理---api版本号策略与版本控制 1. 1.2.1版本概述1 2. 3主版本号策略2 3. 1PATCH版本策略2 3.1. 1.2.2.1次版本号策略2 表3-1 APR中支持 ...

  10. 283. Move Zeroes【easy】

    283. Move Zeroes[easy] Given an array nums, write a function to move all 0's to the end of it while ...