luoguP4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (线段树-权值-动态开点,树链剖分)
中学毕业了,十七号就要前往武汉报道。中学的终点是武汉大学,人生的终点却不是,最初的热情依然失却,我还是回来看看这分类排版皆惨淡的博客吧,只是是用来保存代码也好。想要换一个新博客,带着之前的经验能把它整理得更好。就如人生总渴求一个新的开始,却往往是在过去的殷墟间孑孓独行。既然如此,暂且继续用这个博客吧。中学时的OI结局是我多年来的遗憾,这可能也是支持我果断参加ACM并用整个假期参与多校训练赛的本心吧。我从不相信天才,那只是兴趣遇上合适教育与一点幸运的人,都是一样的。然而,多年来也意识到自己匮乏的天分与耽误的时光,不由想到刚起程的ACM也可能以新的遗憾收尾。可是,不走下去,又怎能见证一路的风景?我不是个积极的人,所以需要一个方向指引我,只是回忆路边的景致就令我沉醉。我刚开始的时候,DEV连c++11都不支持,而现在,我习惯了用C++20,所以,多少是有点改变的,是吧?过去的憧憬,如今的理性,像两颗枝蔓不断衍生的线段树,就这样合并起来。把路上的一切剖分,锁定每个节点对应的色彩,又一点点开出新的节点,一路上,差分,合并,统计,便是答案
# include "bits/stdc++.h"
using namespace std;
constexpr int N = 1e5 + 3;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector G(n + 1, vector<int>());
for(int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
vector<int> fa(n + 1), siz(n + 1), dep(n + 1), son(n + 1, 0);
dep[0] = 0;
auto dfs_first = [&](auto dfs_first, int u, int father) -> void {
fa[u] = father, siz[u] = 1, dep[u] = dep[father] + 1;
for(auto v : G[u]) {
if(v == father) continue;
dfs_first(dfs_first, v, u);
siz[u] += siz[v];
if(siz[son[u]] < siz[v]) son[u] = v;
}
};
dfs_first(dfs_first, 1, 0);
vector<int> top(n + 1);
auto dfs_second = [&](auto dfs_second, int u, int ancestor) -> void {
top[u] = ancestor;
if(!son[u]) return;
dfs_second(dfs_second, son[u], ancestor);
for(auto v : G[u]) {
if(son[u] != v && fa[u] != v) {
dfs_second(dfs_second, v, v);
}
}
};
dfs_second(dfs_second, 1, 1);
struct node {
int l, r, id, val; // id -> color
} t[N << 6]; // weight segment tree : for each color, build a tree
vector<int> rt(n + 1, 0);
int tree_index = 0;
# define ls t[rt].l
# define rs t[rt].r
# define lson t[rt].l, l, mid
# define rson t[rt].r, mid + 1, r
auto push_up = [&](int rt) -> void {
if(t[ls].val < t[rs].val) { // if the same, output the smaller color-index
t[rt].val = t[rs].val;
t[rt].id = t[rs].id;
}
else {
t[rt].val = t[ls].val;
t[rt].id = t[ls].id; // id -> color
}
};
vector<int> ans(n + 1, 0);
while(m--) {
int x, y, col;
cin >> x >> y >> col;
auto LCA = [&](int x, int y) -> int {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) x ^= y ^= x ^= y;
x = fa[top[x]];
}
return dep[x] < dep[y] ? x : y;
};
int lca = LCA(x, y);
auto update = [&](auto update, int &rt, int l, int r, int col, int val) -> void {
if(!rt) rt = ++tree_index;
if(l == r) {
t[rt].val += val;
t[rt].id = col;
return;
}
int mid = l + r >> 1;
if(col <= mid)
update(update, lson, col, val);
else
update(update, rson, col, val);
push_up(rt);
};
update(update, rt[x], 1, N - 1, col, 1);
update(update, rt[y], 1, N - 1, col, 1);
update(update, rt[lca], 1, N - 1, col, -1);
if(lca != 1) update(update, rt[fa[lca]], 1, N - 1, col, -1);
}
auto merge = [&](auto merge, int x, int y, int l, int r) -> int { // x, y -> different segment tree
if(!x || !y) return x | y;
if(l == r) { // l == r -> (x, y -> same color node)
t[x].val += t[y].val;
return x;
}
int mid = l + r >> 1;
t[x].l = merge(merge, t[x].l, t[y].l, l, mid);
t[x].r = merge(merge, t[x].r, t[y].r, mid + 1, r);
push_up(x);
return x;
};
auto dfs = [&](auto dfs, int u, int father) -> void {
for(auto v : G[u]) {
if(v == father) continue;
dfs(dfs, v, u);
rt[u] = merge(merge, rt[u], rt[v], 1, N - 1);
}
if(t[rt[u]].val) {
ans[u] = t[rt[u]].id;
}
};
dfs(dfs, 1, 0);
for(int i = 1; i <= n; ++i) cout << ans[i] << "\n"[i == n];
return 0;
}
luoguP4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (线段树-权值-动态开点,树链剖分)的更多相关文章
- 「Luogu4556」Vani有约会-雨天的尾巴
「Luogu4556」Vani有约会-雨天的尾巴 传送门 很显然可以考虑树上差分+桶,每次更新一条链就是把这条链上的点在桶对应位置打上 \(1\) 的标记, 最后对每个点取桶中非零值的位置作为答案即可 ...
- [Vani有约会]雨天的尾巴 线段树合并
[Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...
- 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告
P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...
- P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)
P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...
- P4556 [Vani有约会]雨天的尾巴 (线段树合并)
P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...
- [题解] P4556 [Vani有约会]雨天的尾巴
[题解] P4556 [Vani有约会]雨天的尾巴 ·题目大意 给定一棵树,有m次修改操作,每次修改 \(( x\) \(y\) \(z )\) 表示 \((x,y)\) 之间的路径上数值 \(z\) ...
- P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)
显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- [Vani有约会]雨天的尾巴
嘟嘟嘟 看到链上操作,自然想到树剖. 先考虑序列上的问题:那么区间修改可以用差分.所以我们把操作拆成\(L\)和\(R + 1\)两个点,然后离线.排序后扫一遍,用线段树维护数量最多的颜色是哪一个. ...
随机推荐
- 【单片机】CH32V103v8t6开发板调试笔记
一.开发板样式和资源 找官网的商务申请了一块开发板,打算试一下串口打印程序测试,发现网上关于这个板子的相关资料特别少,为方便后来人,就顺便记录一下,板子资源如下图所示. 板子芯片的引脚排布图 二.使用 ...
- 项目下载依赖后面加 -S -D -g 分别代表什么意思
npm install name -S此依赖是在package的dependencies中,不仅在开发中,也在打包上线后的生产环境中,比如vue npm install name -D此依赖是在pac ...
- linux-ext4格式文件误删除,该如何恢复?
在开始进行实验之前,我已经新建了一个空目录/data,并将该目录挂载了一块新硬盘,将硬盘分区格式化为ext4的格式,所以当我操作/data目录下的文件及文件夹的时候,实际上就是针对新挂载的硬盘进行数据 ...
- Java - 六原则一法则
Java - 六原则一法则 单一职责原则:一个类只做它该做的事情.(单一职责原则想表达的就是"高内聚",写代码最终极的原则只有六个字"高内聚.低耦合",所谓的高 ...
- 渗透测试之常用的sql语句
学习路漫漫,常用的sql语句给我们平常所运用的sql语句相差不多,用句土话讲:百变不离其中 注:网络安全时刻警醒,需要打靶的还需要建立自己的靶场,关注博主在以往博客中分享有多种创建靶场可参考 1.判断 ...
- Java泛型知识总结
泛型 前言 在没有泛型之前,程序员必须使用Object编写适用于多种类型的代码.很繁琐,也不安全. 泛型的引入使Java有了一个很强的类型系统,允许设计者详细地描述变量和方法的类型要如何变化. 在普通 ...
- Vue回炉重造之封装防刷新考试倒计时组件
<!-- 考试倒计时组件 --> <template> <div class="time"> <p>00:{{timerCount2 ...
- SAP string 转 number 类型
try. cl_fdt_calculation=>convert_string_to_number( exporting iv_text = conv #( lwa_at ...
- DotNET程序员面向API编程的正确姿势
原文:https://blog.csdn.net/u013201439/article/details/49981071 补充:按照步骤成功加载文档后,选择索引可以快速发现相关的内容,如图
- zabbix监控mysql主从同步
获取主从复制sql线程和I/O线程状态是否为yes #!/bin/bash HOSTNAME="数据库IP" PORT="端口" USERNAME=" ...