http://uoj.ac/problem/150

用树链剖分求lca,二分答案树上差分判断。

时间复杂度$O(nlogn)$,n,m同阶。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 300003;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct QQ {int u, v, lca, len;} Q[N];
struct node {int nxt, to, w;} E[N << 1];
int n, m, cnt = 0, point[N], size[N], son[N], top[N], deep[N], fa[N];
int DFN[N], tot = 0, dis[N], fa_dis[N]; void ins(int u, int v, int w) {
E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;
} void _(int x) {
size[x] = 1; DFN[++tot] = x;
for(int i = point[x]; i; i = E[i].nxt)
if (E[i].to != fa[x]) {
fa[E[i].to] = x;
deep[E[i].to] = deep[x] + 1;
dis[E[i].to] = dis[x] + E[i].w;
fa_dis[E[i].to] = E[i].w;
_(E[i].to);
size[x] += size[E[i].to];
if (size[E[i].to] > size[son[x]])
son[x] = E[i].to;
}
} void __(int x) {
if (!son[x]) return;
top[son[x]] = top[x];
__(son[x]);
for(int i = point[x]; i; i = E[i].nxt)
if (E[i].to != son[x] && E[i].to != fa[x])
{top[E[i].to] = E[i].to; __(E[i].to);}
} int LCA(int u, int v) {
while (top[u] != top[v]) {
if (deep[top[u]] < deep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return deep[u] < deep[v] ? u : v;
} int del[N], cont, maxnow; bool check(int s) {
cont = 0; maxnow = 0;
memset(del, 0, sizeof(int) * (n + 1));
for(int i = 1; i <= m; ++i)
if (Q[i].len > s) {
++del[Q[i].u];
++del[Q[i].v];
del[Q[i].lca] -= 2;
++cont;
maxnow = max(maxnow, Q[i].len - s);
} if (!cont) return true;
for(int i = n; i > 1; --i) del[fa[DFN[i]]] += del[DFN[i]];
for(int i = 2; i <= n; ++i)
if (fa_dis[i] >= maxnow && del[i] == cont)
return true;
return false;
} int main() {
n = in(); m = in();
int u, v, w;
for(int i = 1; i < n; ++i) {
u = in(); v = in(); w = in();
ins(u, v, w);
ins(v, u, w);
} _(1);
top[1] = 1; __(1); int left = 0, right = 0, mid;
for(int i = 1; i <= m; ++i) {
Q[i].u = in(); Q[i].v = in();
Q[i].lca = LCA(Q[i].u, Q[i].v);
Q[i].len = dis[Q[i].u] + dis[Q[i].v] - (dis[Q[i].lca] << 1);
right = max(right, Q[i].len);
} while (left < right) {
mid = (left + right) >> 1;
if (check(mid)) right = mid;
else left = mid + 1;
} printf("%d\n", left);
return 0;
}

QwQ

【UOJ #150】【NOIP 2015】运输计划的更多相关文章

  1. 4632 NOIP[2015] 运输计划

    4632 NOIP[2015] 运输计划  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master 题解       题目描述 Description 公元 2044 ...

  2. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

  3. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  4. cogs 2109. [NOIP 2015] 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分

    2109. [NOIP 2015] 运输计划 ★★★☆   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:3 s   内存限制:256 MB [题 ...

  5. NOIP[2015] 运输计划

    传送门 题目描述 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球 ...

  6. [noip 2015]运输计划 [LCA][树链剖分]

    用了luogu上的题目描述 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的 ...

  7. NOIP 2015运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  8. NOIP[2015] 运输计划(codevs 4632)

    题目描述 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P ...

  9. noip 2015 运输计划 (lca+二分)

    /* 95 最后一个点T了 qian lv ji qiong 了 没学过树剖 听chx听xzc说的神奇的方法 Orz 首先求出每个计划的路径长度 这里写的倍增 然后二分答案 对于每个ans 统计> ...

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

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

随机推荐

  1. js获取鼠标位置的各种方法

    在一些DOM操作中我们经常会跟元素的位置打交道,鼠标交互式一个经常用到的方面,令人失望的是不同的浏览器下会有不同的结果甚至是有的浏览器下没结果,这篇文章就上鼠标点击位置坐标获取做一些简单的总结,没特殊 ...

  2. Codeforces 687B. Remainders Game[剩余]

    B. Remainders Game time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  3. u3d单词学习plane

    plane n.水平: 平面: 飞机: 木工刨

  4. Hibernate之组件映射

    1:为什么要使用组件映射 答:建立关系数据模型的一个重要原则是在不会导致数据冗余的前提下,尽可能减少数据库表的数目及表之间的外键参照关系.以员工信息为例,员工信息中有员工的家庭地址信息,如果把地址信息 ...

  5. Java面向对象编程之异常处理机制

    一:Java的异常处理机制的优点: 1:把各种不同情况的异常情况分类,使用JAVA类来表示异常情况,这种类被称为异常类.把各种异常情况表示成异常类,可以充分的发挥类的可扩展性和可重用性. 2:异常流程 ...

  6. java 26 - 6 网络编程之 TCP协议 传输思路 以及 代码

    TCP传输 Socket和ServerSocket 建立客户端和服务器 建立连接后,通过Socket中的IO流进行数据的传输 关闭socket 同样,客户端与服务器是两个独立的应用程序 TCP协议发送 ...

  7. EF的入门使用 (电影管理)

    控制器代码: public class HomeController : Controller { private NewDBContext ndc = new NewDBContext(); pub ...

  8. addClass, removeClass, toggleClass(从jquery中抠出来)

    <div id="d3" class="cur"></div> var mylibs = (function(){ var rtrim ...

  9. offsetLeft与offsetTop详解

    offsetLeft与offsetTop使用方法一样,只是一个是找距离定位父级(position:relative)左边的距离,一个是找距离定位父级上边的距离 没有定位则找body,我们还是看看ie7 ...

  10. 源码安装mysql

    1. 安装依赖组件 # yum install gcc gcc-c++ ncurses-devel perl -y   2. 安装cmake # wget http://www.cmake.org/f ...