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

最新文章

  1. weblogic的集群与配置
  2. node.js安装及grunt插件,如何进行脚本压缩
  3. Kail安装Parallels tools
  4. pydev package包中__init__.py作用
  5. 深入浅出Node.js (8) - 构建Web应用
  6. struts2_20140720
  7. 《Qt编程的艺术》——8.2 显示目录层次
  8. 使用POI生成Excel报表
  9. POJ 2031 Building a Space Station 最小生成树模板
  10. REST Adapter实现SAP PI中的增强XML/JSON格式转换
  11. shiro授权
  12. SecureCRT 7.3注册机激活
  13. json pickle ;shelve
  14. 女皇武则天:我不愿被 extends
  15. 一个人工智能教程,教案接地气、限制级。 http://www.captainbed.net
  16. NPOI 导出Excel部分
  17. Scala 入门介绍
  18. php 获取数组深度的值
  19. [leetcode]45. Jump Game II青蛙跳(跳到终点最小步数)
  20. nodejs+nginx获取真实ip

热门文章

  1. 怎样实现ZBrush中的智能对称
  2. hihocoder #1388 : Periodic Signal NTT&amp;FFT
  3. java 23 - 3 单例模式实现Runtime类
  4. 编译php-5.6出错,xml2-config not found
  5. js继承《转》
  6. tree命令的使用
  7. HFSS学习
  8. 更好的逐帧动画函数 — requestAnimationFrame 简介
  9. 前端Mvvm QC 设计解析
  10. HTML5+JS 《五子飞》游戏实现(一)规则