CF176E Archaeology
有一棵 \(n\) 个点的带权树,每个点都是黑色或白色,最初所有点都是白色的。有 \(m\) 个询问:
- 把点 \(x\) 从白色变成黑色
- 把点 \(x\) 从黑色变成白色
- 查询黑点的导出子树的边权和
\(1 \leq n,\ q \leq 10^5,\ 1\leq x\leq n\) 。
LCA
结论:
- 按照时间戳把所有黑点升序排序,累加相邻及首尾两点之间的路径长度,最后得到的结果恰好是所求答案的两倍
于是可以用一个数据结构按照时间戳递增的顺序维护黑点序列,算插/删点的贡献用 \(lca\) 维护
这个数据结构需要支持插入、求前驱后继,直接用 \(set\) 就吼辣
时间复杂度 \(O(n\log n)\)
代码
#include <bits/stdc++.h>
using namespace std;
#define iter set <int> :: iterator
typedef long long ll;
const int maxn = 1e5 + 10;
ll ans, dis[maxn];
int n, m, tid[maxn], rk[maxn], h[maxn];
int sz[maxn], fa[maxn], dep[maxn], son[maxn], top[maxn];
set <int> seq;
struct edges {
int nxt, to, w;
} e[maxn << 1];
void addline(int u, int v, int w) {
static int cnt = 1;
e[++cnt] = edges{h[u], v, w}, h[u] = cnt;
}
int dfs1(int u, int f) {
fa[u] = f, dep[u] = dep[f] + 1;
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != f) {
dis[v] = dis[u] + e[i].w;
sz[u] += dfs1(v, u);
if (sz[son[u]] < sz[v]) {
son[u] = v;
}
}
}
return ++sz[u];
}
void dfs2(int u, int tp) {
static int now;
top[u] = tp;
tid[u] = ++now, rk[now] = u;
if (son[u]) dfs2(son[u], tp);
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u] && v != son[u]) {
dfs2(v, v);
}
}
}
ll lca(int u, int v) {
ll res = dis[u] + dis[v];
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) {
u = fa[top[u]];
} else {
v = fa[top[v]];
}
}
int _lca = dep[u] < dep[v] ? u : v;
return res - 2 * dis[_lca];
}
ll query(iter it) {
iter pre = it, nxt = it;
pre = it == seq.begin() ? seq.end() : it, pre--;
if (++nxt == seq.end()) nxt = seq.begin();
int l = rk[*pre], r = rk[*nxt], u = rk[*it];
return lca(l, u) + lca(u, r) - lca(l, r);
}
int main() {
scanf("%d", &n);
for (int i = 1, u, v, w; i < n; i++) {
scanf("%d %d %d", &u, &v, &w);
addline(u, v, w), addline(v, u, w);
}
dfs1(1, 0), dfs2(1, 1);
scanf("%d", &m);
iter it, tmp;
char c; int x;
while (m--) {
scanf("%s", &c);
if (c == '?') {
printf("%I64d\n", ans >> 1);
continue;
}
scanf("%d", &x);
if (c == '+') {
it = seq.insert(tid[x]).first;
if (seq.size() > 2) {
ans += query(it);
} else if (seq.size() == 2) {
tmp = it == seq.begin() ? ++it : seq.begin();
ans = lca(rk[*tmp], x) << 1;
}
} else {
it = seq.find(tid[x]);
if (seq.size() > 2) {
ans -= query(it);
} else if (seq.size() == 2) {
ans = 0;
}
seq.erase(tid[x]);
}
}
return 0;
}
CF176E Archaeology的更多相关文章
- CF176E Archaeology(set用法提示)
题目大意: 给一棵树,每次激活或熄灭一个点,每次问这些点都联通起来所需的最小总边权 分析: 若根据dfs序给所有点排序,为$v1,v2,v3....vk$,那么答案就是$(dis(v1,v2)+dis ...
- Codeforces 1178E. Archaeology
传送门 首先一定有解,考虑归纳法证明 首先 $n<=3$ 时显然 考虑 $n=4$ 时,那么因为 $s[1]!=s[2],s[3]!=s[4]$ ,并且 $s[i] \in {a,b,c}$ 由 ...
- CF 1178E Archaeology 题解
题面 这道题竟然是E?还是洛谷中的黑题? wow~!! 于是就做了一下: 然后一下就A了:(这并不代表想的容易,而是写的容易) 这道题就是骗人的!! 什么manacher,什么回文自动机,去靠一边站着 ...
- Codeforces 1178E Archaeology (鸽巢原理)
题意: 给你1e6的字符串,保证只含'a''b''c'三种字符,且相邻两个字符一定不一样 求一个大于等于n/2的回文子序列 思路: 朴素的最长回文子序列是n方的区间dp,这题显然不行,要充分利用题中所 ...
- UVALive 7267 Mysterious Antiques in Sackler Museum (判断长方形)
Sackler Museum of Art and Archaeology at Peking University is located on a beautiful site near the W ...
- What Can I Do With This Major?
What Can I Do With This Major? Majors Don’t see your major? Accounting Advertising Africana Studies ...
- 49、word2vec - tensorflow
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32Type & ...
- How To Make A Swipeable Table View Cell With Actions – Without Going Nuts With Scroll Views
How To Make A Swipeable Table View Cell With Actions – Without Going Nuts With Scroll Views Ellen S ...
- css页面组件
页面组件 1 元素的尺寸/边框/背景 1.1 css尺寸相关属性 height 高度 min-height 最小高度 max-height 最大高度 width 宽度 min-width 最小宽度 m ...
随机推荐
- 精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解!
原文:https://github.com/Chalarangelo/30-seconds-of-code#anagrams-of-string-with-duplicates 作者:Chalaran ...
- 通过 python ssh库连接并发送命令给设备
import paramiko import time hostname = '192.168.248.156' port = 22 user = 'zhou' passwd = ' paramiko ...
- 切换横竖屏的时候Activity的生命周期变化情况
关于这个,有个博客说得比较清楚:http://blog.csdn.net/wulianghuan/article/details/8603982,直接给出链接,哈哈哈.
- Android Studio 之 注释模板
我们看有的项目的文档,会发现它的注释写的很好看,很规范. 而如果你的代码注释还是在用简单的 // 或者 /**/ ,那就学习一下在Android Studio中如何进行注释模板的设置 首先看下面代码 ...
- uni-app 父组件引用子组件时怎么调用子组件的方法
1.写一个简单的子组件main/index.vue: <template> <view> </view> </template> <script& ...
- sql语句中的join用法(可视化解释)
一.innerjoin innerjoin总结来说就是 ,如A知道通往B如何走:B知道通往C如何走:但是A不知道通往C如何走,但是A可以通过B获得去往C的通往方式.. 首先,假设有A,B两张表,结构及 ...
- Jenkins版本升级
前言 我们的内网打包环境目前是运行在windows上,采用jenkins.msi 安装成windwos服务的形式. 升级前准备 在jenkins版本升级之后,我使用ThinBackup进行了备份,详细 ...
- 通过jquery隐藏和显示元素
通过jquery隐藏和显示元素 调用jquery本身提供的函数 $("xxx").hide();//隐藏xxx $("xxx").show();//显示xxx ...
- php学习----什么是常量
PHP-什么是常量 1.什么是常量?常量可以理解为值不变的量(如圆周率):或者是常量值被定义后,在脚本的其他任何地方都不可以被改变.PHP中的常量分为自定义常量和系统常量(后续小节会详细介绍). 2. ...
- SAP事物代码
事物代码是SAP进入特定功能的快捷命令,如事物代码VA01能快速进入创建销售订单的页面,要浏览当前页面的事物代码,在状态栏右下角可以查看 快速导航事物代码 这类事物代码将功能相似的事物代码组合在一起, ...