中学毕业了,十七号就要前往武汉报道。中学的终点是武汉大学,人生的终点却不是,最初的热情依然失却,我还是回来看看这分类排版皆惨淡的博客吧,只是是用来保存代码也好。想要换一个新博客,带着之前的经验能把它整理得更好。就如人生总渴求一个新的开始,却往往是在过去的殷墟间孑孓独行。既然如此,暂且继续用这个博客吧。中学时的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有约会]雨天的尾巴 /【模板】线段树合并 (线段树-权值-动态开点,树链剖分)的更多相关文章

  1. 「Luogu4556」Vani有约会-雨天的尾巴

    「Luogu4556」Vani有约会-雨天的尾巴 传送门 很显然可以考虑树上差分+桶,每次更新一条链就是把这条链上的点在桶对应位置打上 \(1\) 的标记, 最后对每个点取桶中非零值的位置作为答案即可 ...

  2. [Vani有约会]雨天的尾巴 线段树合并

    [Vani有约会]雨天的尾巴 LG传送门 线段树合并入门好题. 先别急着上线段树合并,考虑一下这题的暴力.一看就是树上差分,对于每一个节点统计每种救济粮的数量,再一遍dfs把差分的结果统计成答案.如果 ...

  3. 洛谷 P4556 [Vani有约会]雨天的尾巴 解题报告

    P4556 [Vani有约会]雨天的尾巴 题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒 ...

  4. P4556 [Vani有约会]雨天的尾巴(线段树合并+lca)

    P4556 [Vani有约会]雨天的尾巴 每个操作拆成4个进行树上差分,动态开点线段树维护每个点的操作. 离线处理完向上合并就好了 luogu倍增lca被卡了5分.....于是用rmq维护.... 常 ...

  5. P4556 [Vani有约会]雨天的尾巴 (线段树合并)

    P4556 [Vani有约会]雨天的尾巴 题意: 首先村落里的一共有n座房屋,并形成一个树状结构.然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋 ...

  6. [题解] P4556 [Vani有约会]雨天的尾巴

    [题解] P4556 [Vani有约会]雨天的尾巴 ·题目大意 给定一棵树,有m次修改操作,每次修改 \(( x\) \(y\) \(z )\) 表示 \((x,y)\) 之间的路径上数值 \(z\) ...

  7. P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 (树上差分+线段树合并)

    显然的树上差分问题,最后要我们求每个点数量最多的物品,考虑对每个点建议线段树,查询子树时将线段树合并可以得到答案. 用动态开点的方式建立线段树,注意离散化. 1 #include<bits/st ...

  8. 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)

    题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...

  9. [Vani有约会]雨天的尾巴

    嘟嘟嘟 看到链上操作,自然想到树剖. 先考虑序列上的问题:那么区间修改可以用差分.所以我们把操作拆成\(L\)和\(R + 1\)两个点,然后离线.排序后扫一遍,用线段树维护数量最多的颜色是哪一个. ...

随机推荐

  1. 《Effective C++》阅读总结(四): 设计、声明与实现

    第四章: 设计与声明 18. 让接口更容易被正确使用,不易被误用 将你的class的public接口设计的符合class所扮演的角色,必要时不仅对传参类型限制,还对传参的值域进一步限制. 19. 设计 ...

  2. 分布式机器学习:PageRank算法的并行化实现(PySpark)

    1. PageRank的两种串行迭代求解算法 我们在博客<数值分析:幂迭代和PageRank算法(Numpy实现)>算法中提到过用幂法求解PageRank. 给定有向图 我们可以写出其马尔 ...

  3. nginx 部署前端资源的最佳方案

    前言 最近刚来一个运维小伙伴,做线上环境的部署的时候,前端更新资源后,总是需要清缓存才能看到个更新后的结果.客户那边也反馈更新了功能,看不到. 方案 前端小伙伴应该都知道浏览器的缓存策略,协商缓存和强 ...

  4. LoRa和NB-IoT会长期共存吗?

    物联网有很多无线通信技术,主要是Zigbee,WiFi,蓝牙和Z-wave等短距离通信技术,另一种是LPWAN.LPWAN的两种类型之一在未授权的频谱上工作.另一种是2G/3G/4G蜂窝通信技术,该技 ...

  5. D3.JS结合Canvas实现直方图,散点图,等高线图,密度图

    接触到D3.JS,感觉在图表方面实现的很好,于是深入了解了一下,想在项目中使用, 可是当看到DEMO时才发现,基本上所有的DEMO都是基于SVG,虽然D3.JS声称支持CANVAS,可并没有发现一例使 ...

  6. 在.NET 6.0上使用Kestrel配置和自定义HTTPS

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 本章是<定制ASP NET 6.0框架系列文章>的第四篇.在本章,我们 ...

  7. Android Studio 的初次使用

    记录我第一次使用Android Studio时遇到的问题以及一些简单的笔记. 我所使用的是Android Studio 2.2版本 遇到的问题 创建一个Hello World!项目无疑是相当简单的,我 ...

  8. MarkDown语法——更好地写博客

    MarkDown语法--更好地写博客 我们在学习过程中要尽量养成编写博客的 好习惯:一方面方便自己在学习之后进行一次汇总,其次自己书写的文章可以在以后的时间里反复查看以便于巩固,在找工作时博客也是被招 ...

  9. Kafka 延时队列&重试队列

    一.延时队列 1. 简介 TimingWheel是kafka时间轮的实现,内部包含了⼀个TimerTaskList数组,每个数组包含了⼀些链表组成的TimerTaskEntry事件,每个TimerTa ...

  10. Tapdata Cloud 版本上新!新增TiDB等数据源支持,连接和任务功能增强,体验更优

    Tapdata Cloud cloud.tapdata.net Tapdata Cloud 是国内首家异构数据库实时同步云平台,目前支持Oracle.MySQL.PG.SQL Server.Mongo ...