题目链接: Tree Path

大致题意

给定一棵有nnn个节点的树, 其中有kkk条有权路径(保证不同路径边权互不相同), 有mmm次如下操作:

0: 删除树中权值最小的路径

1 x: 询问树中删除x节点后, 剩余连通边权中的最小值.

解题思路

相似题目参考

本题的查询操作, 属于上题的强制在线版本, 因此我们可以用上题中类似的方式实现.

推荐大家先去做上面这道题, 题解思路都详细一些. 做完后再回来看这道题, 你会发现处理手段几乎是一模一样的.


首先我们考虑查询操作, 我们需要每次对删除节点x的连通路径上的最小边权.

同上题处理方法, 我们每次修改路径(a,b)(a, b)(a,b)的权值时, 变为修改其补集. 这样每个节点所维护的权值就是不包含该点时, 剩余连通边权中的最小值.

这样, 我们就解决了查询操作.


关于本题的修改操作, 由于每次都是删除权值最小的边, 因此我们没有必要再用双堆的方式去维护了, 我们可以开一个全局变量, 记录被删除掉的数值即可.


特别的, 线段树内推荐维护优先队列, 如果维护set, 会增加时间/空间常数复杂度.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E5 + 10, INF = 0x3f3f3f3f;
int n, k, m;
/* 离散化模版 */
vector<int> v(1, -0x3f3f3f3f); // int len;
int find(int x) { return lower_bound(v.begin(), v.end(), x) - v.begin(); }
void discrete() { sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); }
bool del[N];/* 树链剖分模版 */
int w[N];
vector<int> edge[N];
struct EDGE { int a, b, c; }EG[N];int p[N], dep[N], sz[N], son[N];
void dfs1(int x = 1, int fa = 0) {p[x] = fa, dep[x] = dep[fa] + 1, sz[x] = 1; // son[x] = 0;for (auto& to : edge[x]) {if (to == fa) continue;dfs1(to, x);sz[x] += sz[to];if (sz[to] > sz[son[x]]) son[x] = to;}
}
int id[N], nw[N], top[N], ind;
void dfs2(int x = 1, int tp = 1) {id[x] = ++ind, nw[ind] = w[x], top[x] = tp;if (!son[x]) return;dfs2(son[x], tp);for (auto& to : edge[x]) {if (to == p[x] or to == son[x]) continue;dfs2(to, to);}
}/* 线段树模版 */
struct SEG {struct node {int l, r;priority_queue<int, vector<int>, greater<>> val;int top() {while (!val.empty() and del[val.top()]) val.pop();return val.empty() ? INF : val.top();}}t[N << 2];void build(int l, int r, int x = 1) {t[x] = { l, r };if (l == r) return;int mid = l + r >> 1;build(l, mid, x << 1), build(mid + 1, r, x << 1 | 1);}void modify(int l, int r, int c, int x = 1) {if (l <= t[x].l and r >= t[x].r) {t[x].val.push(c);return;}int mid = t[x].l + t[x].r >> 1;if (l <= mid) modify(l, r, c, x << 1);if (r > mid) modify(l, r, c, x << 1 | 1);}int ask(int a, int x = 1) {if (t[x].l == t[x].r) return t[x].top();int mid = t[x].l + t[x].r >> 1;return min(t[x].top(), ask(a, x << 1 | (a > mid)));}
}seg;void modify_route(int a, int b, int c) {vector<pair<int, int>> area;while (top[a] != top[b]) {if (dep[top[a]] < dep[top[b]]) swap(a, b);area.push_back({ id[top[a]], id[a] });a = p[top[a]];}if (id[a] > id[b]) swap(a, b);area.push_back({ id[a], id[b] });sort(area.begin(), area.end());int L = 1;// [L, l - 1], L = r + 1for (auto& [l, r] : area) {if (L <= l - 1) seg.modify(L, l - 1, c);L = r + 1;}if (L <= n) seg.modify(L, n, c);
}
int main()
{cin >> n >> k >> m;rep(i, n - 1) {int a, b; scanf("%d %d", &a, &b);edge[a].push_back(b), edge[b].push_back(a);}dfs1(), dfs2();seg.build(1, n);rep(i, k) {int a, b, c; scanf("%d %d %d", &a, &b, &c);EG[i] = { a, b, c };v.push_back(c);}discrete();rep(i, k) {auto& [a, b, c] = EG[i];c = find(c);modify_route(a, b, c);}int last = 0, delindex = 0;rep(i, m) {int tp; scanf("%d", &tp);if (!tp) del[++delindex] = 1;else {int x; scanf("%d", &x); x ^= last;int res = seg.ask(id[x]);last = res == INF ? -1 : v[res];printf("%d\n", last);}}return 0;
}

END

2022东北四省赛 F. Tree Path (树剖 + 线段树维护堆)相关推荐

  1. 2019ICPC西安邀请赛 E. Tree(树剖 + 线段树)

    Tree 给定一棵树,节点有点权,然后有三种操作: 一.修改1−>s1->s1−>s的路径上的点权与ttt进行按位或. 二.修改1−>s1->s1−>s的路径上的点 ...

  2. 2021 Jiangsu Collegiate Programming Contest F. Jumping Monkey II 树剖+线段树

    F. Jumping Monkey II 题意: 给你 n = 2 e 5 n=2e5 n=2e5的一棵树,每个点有点权 a [ i ] < = 1 e 9 a[i]<=1e9 a[i]& ...

  3. 关于2022年TI省赛--F题信号调制度测量装置

    关于2022年TI省赛--F题信号调制度测量装置 赛题分析 理论分析 AM信号处理方案 方案一: 方案二: FM信号处理方案 方案一: 方案二: FFT快速傅里叶变换与逆变换算法 带通抽样定律采样算法 ...

  4. 2018东北四省赛 Store The Matrix (矩阵)

    2018东北四省赛 Store The Matrix (矩阵) 题目描述 Given a matrix M with r rows and c columns. It is obviously tha ...

  5. CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)

    CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)   首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现.      第 ...

  6. 【UOJ#388】【UNR#3】配对树(线段树,dsu on tree)

    [UOJ#388][UNR#3]配对树(线段树,dsu on tree) 题面 UOJ 题解 考虑一个固定区间怎么计算答案,把这些点搞下来建树,然后\(dp\),不难发现一个点如果子树内能够匹配的话就 ...

  7. 东北四省赛H-Skyscraper-线段树的区间合并优化

    题目描述: At the main street of Byteland, there will be built n skyscrapers, standing sequentially one n ...

  8. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  9. CCSU团队训练赛 ( A 数学 B tarjan F dij G dp H 线段树 )

    题目链接 设的私密,可能进不去,每个题有给原题链接.算作是私人题解吧. A - Play the Dice HDU - 4586  There is a dice with n sides, whic ...

  10. ICPC 南昌现场赛 K:Tree(dsu on tree + 动态开点线段树)

    Tree 让我们找满足一下五个条件的(x,y(x, y(x,y)点对有多少: x≠yx \neq yx​=y xxx不是yyy的祖先 yyy不是xxx的祖先 dis(x,y)≤kdis(x, y)\ ...

最新文章

  1. AI Time 7 | 人机交互的终极状态——人机共生
  2. 调用存储过程时报错:There is no ‘username’@'host’ registered
  3. 这应该是最通俗易懂的一篇Spring知识点总结了
  4. flutter - dart基础之map
  5. IDEA把Java Web导出为war文件
  6. OPA 17 - searchField.setValue
  7. Singleton(单件)--对象创建模式
  8. 第三十三期:对于人工智能的恐惧及其5个解决方法
  9. flutter 获取设备屏幕大小
  10. linux listener作用,Local_listener 的作用
  11. 比较标签 php,比较标签 · ThinkPHP5.0完全开发手册 · 看云
  12. java字面量和符号引用_JVM中的直接引用和符号引用
  13. C# Dictionary 的几种遍历方法
  14. PS 钢笔工具如何拖拽滑杆
  15. 关于微服务中用户身份认证的一点愚见
  16. 计算机视觉 — Harris角点检测
  17. 面向模式的软件体系结构(卷1-5
  18. RK3568-B2-ANDROID11-WIFI-RTL8821CU
  19. nmap学习记录(未完待续)
  20. FPGA自学11——以太网通信

热门文章

  1. react从入门到入魔
  2. Python 从入门到入魔
  3. 数字孪生城市优秀案例汇编(2021年) 附下载
  4. 2022-2028全球新冠检测试剂行业调研及趋势分析报告
  5. 程序员慵懒的周末:不想出门还想吃肯德基香辣鸡翅?
  6. 计算机网络批量确认,【02-计算机网络面试核心】01-tcp协议与三次握手/四次挥手...
  7. IMO 2017 T1解答
  8. mysql group by 命令_MySQL常用命令(八)--GROUP BY、HAVING、SELECT子句的顺序
  9. Dockerfile中ADD文件用法
  10. html网页提速,HTML-加速、再加速(上)