下午用一个小时看了一下树上差分,打了个差分模板,A了3题,真的爽!

题目描述:

公元2044 年,人类进入了宇宙纪元。

L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。

为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

数据范围:

n<=300000,m<=300000

思路分析:

首先得写个倍增求LCA求个链长,这应该没问题吧,我之前讲过的(不懂戳这里,你们可能会惊奇地发现下面的代码里我的lca是复的,嘘——)。

那么再看问题,“使最大的运输时间最少”——某王  定理之二十一(滑稽):任何求最大值最小,最小值最大的问题十有八九是二分答案。

嗯,很好,让我们考虑二分答案这种神奇的东西。

对于我们二分出的答案mid,我们应该怎么来判断它是否合法呢?

首先让我们找出这m条链中长度大于mid的,求出链的数量num以及最长链的长度len。

显然,当这num条边中都经过一条长度至少为(len-mid)的边,那么当我们删去这条边后,这个答案就是合法的,因为原本所有长度大于mid的链长度都会小于等于mid。

那么我们应该怎么找这num条链都经过的边呢?——树上差分嘛,没有争议的(不懂的话戳这里)。

代码实现:

var
  f:array[0..300000,0..20]of longint;
  vis:array[0..300000]of boolean;
  next,vet,dist:array[0..600000]of longint;
  head,cnt,depth,g,d,len,u,v,grand:array[0..300000]of longint;
  ans,i,j,n,m,tot,x,y,z,max,num,k,l,r,mid:longint;
  flag:boolean;
procedure add(x,y,z:longint);
begin
  inc(tot);
  next[tot]:=head[x];
  vet[tot]:=y;
  head[x]:=tot;
  dist[tot]:=z;
end;
procedure dfs(u,dep,dis:longint);
var
  i,v:longint;
begin
  depth[u]:=dep; vis[u]:=true;
  for i:=1 to 20 do
    f[u,i]:=f[f[u,i-1],i-1];
  i:=head[u];
  while i<>0 do
  begin
    v:=vet[i];
    if not vis[v] then
    begin
      f[v,0]:=u;
      d[v]:=dis+dist[i];
      dfs(v,dep+1,d[v]);
    end;
  i:=next[i];
  end;
end;
function lca(a,b:longint):longint;
var
  i,t:longint;
begin
  if depth[a]>depth[b] then begin t:=a; a:=b; b:=t; end;
  for i:=20 downto 0 do
    if depth[f[b,i]]>=depth[a] then b:=f[b,i];
  if a=b then exit(a);
  for i:=20 downto 0 do
  if f[a,i]<>f[b,i] then
    begin a:=f[a,i]; b:=f[b,i]; end;
  exit(f[a,0]);
end;
procedure getans(u,father:longint);
var
  i,v:longint;
begin
  g[u]:=cnt[u];
  i:=head[u];
  while i<>0 do
  begin
    v:=vet[i];
    if v<>father then
    begin
      getans(v,u);
      g[u]:=g[u]+g[v];
      if (g[v]=num)and(dist[i]>=k) then flag:=true;
    end;
    i:=next[i];
  end;
end;
function check(x:longint):boolean;
var
  i:longint;
begin
  flag:=false; max:=0; num:=0;
  fillchar(g,sizeof(g),0);
  fillchar(cnt,sizeof(cnt),0);
  for i:=1 to m do
  if len[i]>x then
  begin
    inc(cnt[u[i]]); inc(cnt[v[i]]);
    cnt[grand[i]]:=cnt[grand[i]]-2;
    inc(num);
    if len[i]>max then max:=len[i];
  end;
  k:=max-x;
  getans(1,0);
  exit(flag);
end;
begin
  read(n,m);
  for i:=1 to n-1 do
  begin
    read(x,y,z);
    add(x,y,z); add(y,x,z);
  end;
  dfs(1,1,0);
  for i:=1 to m do
  begin
    read(u[i],v[i]);
    grand[i]:=lca(u[i],v[i]);
    len[i]:=d[u[i]]+d[v[i]]-2*d[grand[i]]; //有没有觉得我今天的码风格外清新,嗯,我用Guide写的代码。
    if len[i]>max then max:=len[i];
  end;
  l:=1; r:=max;
  while l<=r do
  begin
    mid:=(l+r)div 2;
    if check(mid) then begin r:=mid-1; ans:=mid; end else l:=mid+1;
  end;
  writeln(ans);
end.

树型大融合——NOIP提高组2015 D1T3 【运输计划】的更多相关文章

  1. 题解——洛谷 P2680 NOIP提高组 2015 运输计划

    树上差分加上二分答案 详细题解待填坑 #include <cstdio> #include <algorithm> #include <cstring> using ...

  2. 题解 【luogu P2680 NOIp提高组2015 运输计划】

    题目链接 题解 题意 一棵树上有\(m\)条路径,可以将其中一条边的权值改为0,问最长的路径最短是多少 分析 最短的路径最长自然想到二分最长路径,设其为\(dis\) 关键在于如何check chec ...

  3. NOIP提高组 2013货车运输

    觉得题目水的离开 不屑的大佬请离开 不会图论的请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 题面: 题目描述 A 国有 n 座城市,编号从 1 到 ...

  4. NOIP提高组2018 D1T3 【赛道修建】

    颓了好几天,终于把这到题处理了一下. 话说,其实我考场上想出正解了,但是手残,算复杂度的时候多按了一个零,导致算出来是1亿多的复杂度,都不敢打...就把部分分都捡了一下... 题目描述: C 城将要举 ...

  5. 题解 【luoguP1967 NOIp提高组2013 货车运输】

    题目链接 题解 题意 给你一个无向图,求两个点之间的一条路径,使路径上的最小值最大 算法:Kruskal最大生成树+倍增lca 分析 首先容易知道,答案一定在该图的最大生成树上 之后问题便转换成了树上 ...

  6. NOIP提高组初赛难题总结

    NOIP提高组初赛难题总结 注:笔者开始写本文章时noip初赛新题型还未公布,故会含有一些比较老的内容,敬请谅解. 约定: 若无特殊说明,本文中未知数均为整数 [表达式] 表示:在表达式成立时它的值为 ...

  7. NOIP提高组2004 合并果子题解

    NOIP提高组2004 合并果子题解 描述:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消 ...

  8. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  9. [NOIP提高组2018]货币系统

    [TOC] 题目名称:货币系统 来源:2018年NOIP提高组 链接 博客链接 CSDN 洛谷博客 洛谷题解 题目链接 LibreOJ(2951) 洛谷(P5020) 大视野在线评测(1425) 题目 ...

随机推荐

  1. vue-cli3项目配置eslint代码规范

    前言 最近接手了一个项目,由于之前为了快速开发,没有做代码检查.为了使得代码更加规范以及更易读,所以就要eslint上场了. 安装依赖 安装依赖有两种方法: 1. 在cmd中打上把相应的依赖加到dev ...

  2. Java生成1,2,2,3,3,3,4,4,4,4,5...序列

    程序很简单,无须赘述. 竖向输出方式: public class Test { public static void main(String[] args) { int n=0; for(n=1;n& ...

  3. centos7在线yum安装jumpsever2.2.2

    #查看主机名 host=$(hostname) # 修改字符集,否则可能报 input/output error的问题,因为日志里打印了中文 localedef -c -f UTF-8 -i zh_C ...

  4. windows上部署rabbitmq遇到的一些问题及解决方法

    在目前这家公司,刚进公司的时候接手了一个服务,算是个比较完备的服务,其中几台电脑之间通信用到了rabbitmq,一开始没出什么问题,然后后来勒索病毒wanner cry来的时候,系服把所有服务器装了一 ...

  5. Linux下Python3.6的安装及避坑指南

    Python3的安装 1.安装依赖环境 Python3在安装的过程中可能会用到各种依赖库,所以在正式安装Python3之前,需要将这些依赖库先行安装好. yum -y install zlib-dev ...

  6. cmd运行SpringBoot的jar中文乱码

    问题: 通过以下命令启动springBoot项目后,在项目中查看日志,发现中文乱码 java -jar projectName.jar 解决 启动时添加参数-Dfile.encoding=UTF-8即 ...

  7. why哥被阿里一道基础面试题给干懵了,一气之下写出万字长文。

    这是why的第 65 篇原创文章 荒腔走板 大家好,我是 why,欢迎来到我连续周更优质原创文章的第 65 篇.老规矩,先荒腔走板聊聊技术之外的东西. 上面这图是去年的成都马拉松赛道上,摄影师抓拍的我 ...

  8. oracle之网络

    Oracle 网络 sqlplus sys/123123@192.168.143.90:1521/urpdb as sysdba 15.1 Oracle Net 基本要素: 15.1.1 服务器端的l ...

  9. oracle之dblink

    当用户要跨本地Oracle数据库,访问另外一个数据库表中的数据时,本地数据库中必须创建了远程数据库的dblink,通过dblink本地数据库可以像访问本地数据库一样访问远程数据库表中的数据.下面讲介绍 ...

  10. [程序员代码面试指南]递归和动态规划-数字字符串转换为字母组合的种数(DP)

    题意 给一个字符串,只由数字组成,若是'1'-'26',则认为可以转换为'a'-'z'对应的字母,问有多少种转换方法. 题解 状态转移很好想,注意dp多开一位,dp[0]为dp[2]的计算做准备.dp ...