原题链接

每个点开一个权值线段树,然后用树上差分的方法修改,最后自底向上暴力线段树合并即可。

不过空间较大,会\(MLE\),写个内存池就可以了。

#include<cstdio>
#include<cmath>
using namespace std;
const int N = 1e5 + 10;
const int M = 6e6 + 10;
struct dd {
int x, y, z;
};
dd a[N];
int fi[N], di[N << 1], ne[N << 1], ro[N], S[M], CO[M], L[M], R[M], de[N], f[N][18], an[N], sta[M], l, ma, gn, SEG, tp;
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void add(int x, int y)
{
di[++l] = y;
ne[l] = fi[x];
fi[x] = l;
}
inline void sw(int &x, int &y)
{
int z = x;
x = y;
y = z;
}
inline int maxn(int x, int y){ return x > y ? x : y; }
void dfs(int x)
{
int i, y;
for (i = 1; i <= gn; i++)
f[x][i] = f[f[x][i - 1]][i - 1];
for (i = fi[x]; i; i = ne[i])
if (!de[y = di[i]])
{
de[y] = de[x] + 1;
f[y][0] = x;
dfs(y);
}
}
int lca(int x, int y)
{
int i;
if (de[x] > de[y])
sw(x, y);
for (i = gn; ~i; i--)
if (de[f[y][i]] >= de[x])
y = f[y][i];
if (!(x ^ y))
return x;
for (i = gn; ~i; i--)
if (f[x][i] ^ f[y][i])
{
x = f[x][i];
y = f[y][i];
}
return f[x][0];
}
void pp(int r)
{
int lx = L[r], rx = R[r];
if (S[lx] < S[rx])
{
S[r] = S[rx];
CO[r] = CO[rx];
}
else
{
S[r] = S[lx];
CO[r] = CO[lx];
}
}
inline void rec(int x){ sta[++tp] = x; }
inline int NEW(){ return tp ? sta[tp--] : ++SEG; }
void mdf(int &r, int x, int y, int k, int v)
{
if (!r)
r = ++SEG;
if (!(x ^ y))
{
S[r] += v;
S[r] > 0 ? CO[r] = x : CO[r] = 0;
return;
}
int mid = (x + y) >> 1;
k <= mid ? mdf(L[r], x, mid, k, v) : mdf(R[r], mid + 1, y, k, v);
pp(r);
}
int merge(int x, int y, int r_1, int r_2)
{
if (!r_1)
return r_2;
if (!r_2)
return r_1;
int r = NEW();
if (!(x ^ y))
{
S[r] = S[r_1] + S[r_2];
S[r] > 0 ? CO[r] = x : CO[r] = 0;
return r;
}
int mid = (x + y) >> 1;
L[r] = merge(x, mid, L[r_1], L[r_2]);
R[r] = merge(mid + 1, y, R[r_1], R[r_2]);
pp(r);
rec(r_1);
rec(r_2);
return r;
}
void UPD(int x)
{
int i, y;
for (i = fi[x]; i; i = ne[i])
if ((y = di[i]) ^ f[x][0])
{
UPD(y);
ro[x] = merge(1, ma, ro[x], ro[y]);
}
an[x] = CO[ro[x]];
}
int main()
{
int i, n, m, x, y, LCA;
n = re();
m = re();
gn = log2(n);
for (i = 1; i < n; i++)
{
x = re();
y = re();
add(x, y);
add(y, x);
}
de[1] = 1;
dfs(1);
for (i = 1; i <= m; i++)
{
a[i].x = re();
a[i].y = re();
a[i].z = re();
ma = maxn(ma, a[i].z);
}
for (i = 1; i <= m; i++)
{
LCA = lca(a[i].x, a[i].y);
mdf(ro[a[i].x], 1, ma, a[i].z, 1);
mdf(ro[a[i].y], 1, ma, a[i].z, 1);
mdf(ro[LCA], 1, ma, a[i].z, -1);
if (LCA ^ 1)
mdf(ro[f[LCA][0]], 1, ma, a[i].z, -1);
}
UPD(1);
for (i = 1; i <= n; i++)
printf("%d\n", an[i]);
return 0;
}

洛谷4556 [Vani有约会]雨天的尾巴的更多相关文章

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

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

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

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

  3. 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)

    传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...

  4. 洛咕 P4556 [Vani有约会]雨天的尾巴

    终于把考试题清完了...又复活了... 树上差分,合并用线段树合并,但是空间会炸. 某大佬:lca和fa[lca]减得时候一定已经存在这个节点了,所以放进vector里,合并完之后减掉就好了... 玄 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. linux nodejs

    scp node-v8.15.0-linux-x64.tar.gz root@10.88.248.231:/lngoa tar -zxvf node-v8.15.0-linux-x64.tar.gz ...

  2. OLAP + MDX

    基本概念 维度(Dimension):表示数据的属性,一个维度一般会有一个维表(也可能多个),事实表会有一个字段关联维表. 退化维度:有的维度可以没有维度表,因为这种维度比较简单,没有更多属性,没有必 ...

  3. 如何在Windows命令行(DOS界面)中调用 编译器 来编译C/C++源程序

    首先说明一下背景: 为什么要在DOS界面编译C/C++源程序?有很多现成的开发环境(IDE)如:vs, vc++等,这些开发环境集成了编译,调试,使用起来很方便,而且图形化操作界面,简洁明了.但是在开 ...

  4. 【浅色】最强Win7 x64评测

    [浅色]最强Win7 x64评测 [浅色]最强Win7 x86 & x64 | WINOS https://www.winos.me/archives/789.htmlESD671MB,安装后 ...

  5. python函数嵌套定义

    python的这个特性是很特别的,与C#和C++都不一样.请看下面的例子 def outFun(): def innerFun_0():#1.在内部定义一个函数 print("i am fi ...

  6. WordPress版微信小程序2.2.0版发布

    2017年8月12日WordPress版微信小程序2.2.0版通过了微信的审核正式发布,此版本的更新以完善功能为主.主要更新的功能是:站内链接,猜你喜欢,热点文章. WordPress版微信小程序开放 ...

  7. 什么是Java序列化,如何实现java序列化

      简要解释: 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化.可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间. 序列化是为了解决在对对象流进行读写操作时所 ...

  8. gentoo Cataclysm - Dark Days Ahead

    gentoo 中安装 Cataclysm - Dark Days Ahead,使用web 下载稳定版的安装包,使用 tar 进行解压. 安装需要共享库:sdl2-mixer, 未完待续

  9. sql server driver ODBC驱动超时

  10. ELK+Beats日志分析系统部署

    一.            名词介绍: E:ElasticSearch 搜索,简称es L:Logstash 管理日志和事件的工具 K:Kibana 功能强大的数据显示客户端 Beats 轻量级数据传 ...