hdu5993/2016icpc青岛L
zz:https://www.cnblogs.com/ytytzzz/p/9674661.html
题意:
给一棵树,每次询问删掉两条边,问剩下的三棵树的最大直径
点10W,询问10W,询问相互独立
Solution:
考虑线段树/倍增维护树的直径
考虑一个点集的区间 [l, r]
而我们知道了有 l <= k < r,
且知道 [l, k] 和 [k + 1, r] 两个区间的最长链的端点及长度
假设两个区间的直径端点分别为 (l1, r1) 和 (l2, r2)
那么 [l, r] 这个区间的直径长度为
dis(l1, r1) dis(l1, l1) dis(l1, r2)
dis(r1, l2) dis(r1, r2) dis(l2, r2)
六个值中的最大值
本题因为操作子树,所以我们维护dfs序的区间最长链即可
#include <stdio.h>
#include <algorithm> using namespace std; const int N = 2e5 + 5; int T, n, m; int len, head[N], ST[20][N]; struct edge{int u, v, w;}ee[N]; int cnt, fa[N], log_2[N], st[N], en[N], dfn[N], dis[N], dep[N], pos[N]; struct edges{int to, next, cost;}e[N]; inline void add(int u, int v, int w) {
e[++ len] = (edges){v, head[u], w}, head[u] = len;
e[++ len] = (edges){u, head[v], w}, head[v] = len;
} inline void dfs1(int u) {
st[u] = ++ cnt, dfn[cnt] = u;
for (int v, i = head[u]; i; i = e[i].next) {
v = e[i].to;
if (v == fa[u]) continue;
fa[v] = u, dep[v] = dep[u] + 1;
dis[v] = dis[u] + e[i].cost, dfs1(v);
}
en[u] = cnt;
} inline void dfs2(int u) {
dfn[++ cnt] = u, pos[u] = cnt;
for (int v, i = head[u]; i; i = e[i].next) {
v = e[i].to;
if (v == fa[u]) continue;
dfs2(v), dfn[++ cnt] = u;
}
} int mmin(int x, int y) {
if (dep[x] < dep[y]) return x;
return y;
} inline int lca(int u, int v) {
static int w;
if (pos[u] > pos[v]) swap(u, v);
w = log_2[pos[v] - pos[u] + 1];
return mmin(ST[w][pos[u]], ST[w][pos[v] - (1 << w) + 1]);
} inline int dist(int u, int v) {
int Lca = lca(u, v);
return dis[u] + dis[v] - dis[Lca] * 2;
} inline void build() {
for (int i = 1; i <= cnt; i ++)
ST[0][i] = dfn[i];
for (int i = 1; i < 20; i ++)
for (int j = 1; j <= cnt; j ++)
if (j + (1 << (i - 1)) > cnt) ST[i][j] = ST[i - 1][j];
else ST[i][j] = mmin(ST[i - 1][j], ST[i - 1][j + (1 << (i - 1))]);
} int M; struct node {
int l, r, dis;
}tr[N << 1]; inline void update(int o, int o1, int o2) {
static int d;
static node tmp;
if (tr[o1].dis == -1) {tr[o] = tr[o2]; return;}
if (tr[o2].dis == -1) {tr[o] = tr[o1]; return;}
if (tr[o1].dis > tr[o2].dis) tmp = tr[o1];
else tmp = tr[o2];
d = dist(tr[o1].l, tr[o2].l);
if (d > tmp.dis) tmp.l = tr[o1].l, tmp.r = tr[o2].l, tmp.dis = d;
d = dist(tr[o1].l, tr[o2].r);
if (d > tmp.dis) tmp.l = tr[o1].l, tmp.r = tr[o2].r, tmp.dis = d;
d = dist(tr[o1].r, tr[o2].l);
if (d > tmp.dis) tmp.l = tr[o1].r, tmp.r = tr[o2].l, tmp.dis = d;
d = dist(tr[o1].r, tr[o2].r);
if (d > tmp.dis) tmp.l = tr[o1].r, tmp.r = tr[o2].r, tmp.dis = d;
tr[o] = tmp;
} inline void ask(int s, int t) {
if (s > t) return;
for (s += M - 1, t += M + 1; s ^ t ^ 1; s >>= 1, t >>= 1) {
if (~s&1) update(0, 0, s ^ 1);
if ( t&1) update(0, 0, t ^ 1);
}
} inline int get_char() {
static const int SIZE = 1 << 23;
static char *T, *S = T, buf[SIZE];
if (S == T) {
T = fread(buf, 1, SIZE, stdin) + (S = buf);
if (S == T) return -1;
}
return *S ++;
} inline void in(int &x) {
static int ch;
while (ch = get_char(), ch > 57 || ch < 48);x = ch - 48;
while (ch = get_char(), ch > 47 && ch < 58) x = x * 10 + ch - 48;
} int main() {
int u, v, w, ans;
log_2[1] = 0;
for (int i = 2; i <= 200000; i ++)
if (i == 1 << (log_2[i - 1] + 1))
log_2[i] = log_2[i - 1] + 1;
else log_2[i] = log_2[i - 1];
for (in(T); T --; ) {
in(n), in(m), cnt = len = 0;
for (int i = 1; i <= n; i ++)
head[i] = 0;
for (int i = 1; i < n; i ++) {
in(ee[i].u), in(ee[i].v), in(ee[i].w);
add(ee[i].u, ee[i].v, ee[i].w);
}
dfs1(1);
for (M = 1; M < n + 2; M <<= 1);
for (int i = 1; i <= n; i ++)
tr[i + M].l = tr[i + M].r = dfn[i], tr[i + M].dis = 0;
for (int i = n + M + 1; i <= (M << 1) + 1; i ++)
tr[i].dis = -1;
cnt = 0, dfs2(1), build();
for (int i = M; i; i --)
update(i, i << 1, i << 1 | 1);
for (int i = 1; i < n; i ++)
if (dep[ee[i].u] > dep[ee[i].v])
swap(ee[i].u, ee[i].v);
for (int u, v, i = 1; i <= m; i ++) {
in(u), in(v), ans = 0;
u = ee[u].v, v = ee[v].v, w = lca(u, v);
if (w == u || w == v) {
if (w != u) swap(u, v);
tr[0].dis = -1, ask(1, st[u] - 1), ask(en[u] + 1, n), ans = max(ans, tr[0].dis);
tr[0].dis = -1, ask(st[u], st[v] - 1), ask(en[v] + 1, en[u]), ans = max(ans, tr[0].dis);
tr[0].dis = -1, ask(st[v], en[v]), ans = max(ans, tr[0].dis);
}
else {
if (st[u] > st[v]) swap(u, v);
tr[0].dis = -1, ask(1, st[u] - 1), ask(en[u] + 1, st[v] - 1), ask(en[v] + 1, n), ans = max(ans, tr[0].dis);
tr[0].dis = -1, ask(st[u], en[u]), ans = max(ans, tr[0].dis);
tr[0].dis = -1, ask(st[v], en[v]), ans = max(ans, tr[0].dis);
}
printf("%d\n", ans);
}
}
return 0;
}
hdu5993/2016icpc青岛L的更多相关文章
- 倍增/线段树维护树的直径 hdu5993/2016icpc青岛L
题意: 给一棵树,每次询问删掉两条边,问剩下的三棵树的最大直径 点10W,询问10W,询问相互独立 Solution: 考虑线段树/倍增维护树的直径 考虑一个点集的区间 [l, r] 而我们知道了有 ...
- 【心情】2016ICPC青岛站打铁记
Day0 下午到的青岛; 然后就在下面这两个地方转了很久:一直找不到公交站台 路上还看到了一个类似堡垒的东西:感觉屌屌的. 然后在落日的余晖下:我们找到了公交站台; 路上不知道他们在讨论什么:GPS什 ...
- HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加
HDU5988 题意: 有n个区域,每个区域有s个人,b份饭.现在告诉你每个区域间的有向路径,每条路有容量和损坏路径的概率.问如何走可以使得路径不被破坏的概率最小.第一个人走某条道路是百分百不会损坏道 ...
- K-D树
一般用来解决各种二维平面的点对统计,也许一般非正解? 没时间慢慢写了,打完这个赛季后补细节 建树板子: #include <cstdio> #include <locale> ...
- JavaWeb 后端 <二> 之 Servlet 学习笔记
一.Servlet概述 1.什么是Servlet Servlet是一个运行在服务器端的Java小程序,通过HTTP协议用于接收来自客户端请求,并发出响应. 2.Servlet中的方法 public v ...
- HTML5 3D 粒子波浪动画特效DEMO演示
需要thress.js插件: http://github.com/mrdoob/three.js // three.js - http://github.com/mrdoob/three.js ...
- ACM ICPC 2018 青岛赛区 部分金牌题题解(K,L,I,G)
目录: K Airdrop I Soldier Game L Sub-cycle Graph G Repair the Artwork ———————————————————— ps:楼主脑残有点严 ...
- 青岛 2016ICPC 区域现场赛题目
A. Relic Discovery B. Pocket Cube C. Pocky D. Lucky Coins E. Fibonacci F. Lambda Calculus G. Coding ...
- 2016 ICPC青岛站---k题 Finding Hotels(K-D树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...
随机推荐
- u-boot v2018.01 启动流程分析 简单版(转)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_39655765/artic ...
- VS插件CodeRush for Visual Studio发布v19.1.5|新的Inline Lambda重构
CodeRush是一个强大的Visual Studio .NET 插件,它利用整合技术,通过促进开发者和团队效率来提升开发者体验.CodeRush能帮助你以极高的效率创建和维护源代码.Consume- ...
- 分组统计 over(partition by
sum( CASE WHEN ISNULL(b.zl, 0) = 0 THEN C.LLZL ELSE b.zl END * c.pccd * b.sl) over(partition by b.dj ...
- CentOS7安装codeblocks
1.yum -y install epel-release 2.yum clean all && yum makecache 3.yum -y install gtk2-devel c ...
- z-tree的使用
1.参考资料 1)官网:http://www.treejs.cn/v3/api.php 2)z-tree码云:https://gitee.com/zTree/zTree_v3 2.下载解压 案例演示: ...
- 【知识】定时器setTimeout/setInterval执行时this指针指向问题
[问题描述] setTimetout/setInterval中this指针指向window,以下是一个小demo: var demoChange = { key: true, changeFun() ...
- POJ 2492 A Bug's Life (带权并查集 && 向量偏移)
题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配 ...
- [SPOJ20174]DIVCNT3 - Counting Divisors (cube):Min_25筛
分析 首先,STO ywy OTZ,ywy TQL%%%! 说一下这道题用min_25筛怎么做. 容易发现,对于所有质数\(p\),都满足\(f(p)=4\),于是我们就可以直接通过\([1,x]\) ...
- Win7,win10(部分机型) 安装appscan9.0.3.10(可升级)实操流程
Win10部分机型不能很好的兼容appscan,建议使用者用win7系统安装appscan 写于:2018.12.2 IBM Security AppScan Standard 可通过自动执行应用安全 ...
- Spark 2.1.1 源码编译
Spark 2.1.1 源码编译 标签(空格分隔): Spark Spark 源码编译 环境准备与起因 由于线上Spark On Yarn Spark Streaming程序在消费kafka 写入HD ...