中学毕业了,十七号就要前往武汉报道。中学的终点是武汉大学,人生的终点却不是,最初的热情依然失却,我还是回来看看这分类排版皆惨淡的博客吧,只是是用来保存代码也好。想要换一个新博客,带着之前的经验能把它整理得更好。就如人生总渴求一个新的开始,却往往是在过去的殷墟间孑孓独行。既然如此,暂且继续用这个博客吧。中学时的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. js 动画补间 Tween

    1 /* RunningList (触发过程中可以安全的删除自己) 2 如果触发过程中删除(回调函数中删除正在遍历的数组), 不仅 len 没有变(遍历前定义的len没有变, 真实的len随之减少), ...

  2. 聊聊OOP中的设计原则以及访问者模式

    一  设计原则 (SOLID) 1.  S - 单一职责原则(Single Responsibllity Principle) 1.1  定义 一个类或者模块只负责完成一个职责(或功能), 认为&qu ...

  3. U8g2图形库与STM32移植(I2C,软件与硬件)

    U8g2图形库 简介 U8g2 是一个用于嵌入式设备的简易图形库,可以在多种 OLED 和 LCD 屏幕上,支持包括 SSD1306 等多种类型的底层驱动,并可以很方便地移植到 Arduino .树莓 ...

  4. Linux Cgroup v1(中文翻译)(4):Block IO Controller

    Block IO Controller 1 概览 cgroup子系统blkio实现了block io控制器.无论是对存储结构上的叶子节点和还是中间节点,它对各种IO控制策略(proportional ...

  5. Linux服务器安装图形化界面

    Linux服务器安装图形化界面 1.检查有无安装gnome桌面 [root@localhost ~]# rpm -qa |grep gnome 2.查看可安装组件列表 [root@localhost ...

  6. Puppeteer学习笔记 (2)- Puppeteer的安装

    本文链接:https://www.cnblogs.com/hchengmx/p/11009849.html 1. node的下载安装 由于puppeteer是nodejs的一个库,所以首先需要安装no ...

  7. 搭建个人博客,Docsify+Github webhook+JGit解决方案

    一开始博客使用的 Halo,发现问题比较多啊,时不时的莫名其妙主题各种报错,有时候还要升级,麻烦的要死,于是就想弄简单点. 这两天抽空反复倒腾了一遍,不小心还把镜像给尼玛删了,发的文章都没了,痛定思痛 ...

  8. JS:!非

    取非运算符: 开关思想:0为false,1为true: 把一个变量中保存一个布尔值 然后在业务执行时,修改这个变量的值: 为取反 然后通过变量的值执行分支业务 例子: var a = "12 ...

  9. JS:this关键字1

    this 代表了当前的对象,哪个对象调用了this所在的函数,this就代表了哪个对象: 例1: function fn(){ var a = 1; console.log(this) } fn() ...

  10. [WUSTCTF2020]朴实无华-1

    1.打开连接只有如下界面:    2.用bp抓包分析包内数据,未发现有用的信息:    3.进行目录扫描,获得robots.txt文件并进行访问:       4.访问/fAke_f1agggg.ph ...