NC200179 Colorful Tree
题目
题目描述
A tree structure with some colors associated with its vertices and a sequence of commands on it are given. A command is either an update operation or a query on the tree. Each of the update operations changes the color of a specified vertex, without changing the tree structure. Each of the queries asks the number of edges in the minimum connected subgraph of the tree that contains all the vertices of the specified color.
Your task is to find answers of each of the queries, assuming that the commands are performed in the given order.
输入描述
The input consists of a single test case of the following format.
n
\(a_1\) \(b_1\)
. . .
\(a_{n−1}\) \(b_{n−1}\)
\(c_1 ... c_n\)
m
\(command_1\)
. . .
\(command_m\)
The first line contains an integer n \((2 \leq n \leq 100000)\) , the number of vertices of the tree. The vertices are numbered 1 through n. Each of the following n−1 lines contains two integers \(a_i (1 \leq a_i \leq n)\) and \(b_i (1 \leq b_i \leq n)\) , meaning that the i-th edge connects vertices \(a_i\) and \(b_i\) . It is ensured that all the vertices are connected, that is, the given graph is a tree. The next line contains n integers, \(c_1\) through \(c_n\) , where \(c_j (1 \leq c_j \leq 100000)\) is the initial color of vertex j. The next line contains an integer m \((1 \leq m \leq 100000)\) , which indicates the number of commands. Each of the following m lines contains a command in the following format.
U \(x_k\) \(y_k\)
or
Q \(y_k\)
When the k-th command starts with U, it means an update operation changing the color of vertex \(x_k (1 \leq x_k \leq n)\) to \(y_k (1 \leq y_k \leq 100000)\) . When the k-th command starts with Q, it
means a query asking the number of edges in the minimum connected subgraph of the tree that contains all the vertices of color \(y_k (1 \leq y_k \leq 100000)\) .
输出描述
For each query, output the number of edges in the minimum connected subgraph of the tree containing all the vertices of the specified color. If the tree doesn’t contain any vertex of the specified color, output -1 instead.
示例1
输入
5
1 2
2 3
3 4
2 5
1 2 1 2 3
11
Q 1
Q 2
Q 3
Q 4
U 5 1
Q 1
U 3 2
Q 1
Q 2
U 5 4
Q 1
输出
2
2
0
-1
3
2
2
0
题解
知识点:DFS序,LCA,STL。
对于一种颜色,我们新加入一个点 \(x\) ,考虑其贡献。设dfn序左右最近的两个点 \(u,v\) ,那么其贡献为:
\]
可以分类讨论验证,首先一定是选择dfn序最近的两点,其次无论 \(x\) 位于 \(u,v\) 中间,还是一侧,这个式子都是满足的。其中对于一侧情况,我们统一取第一个点和最后一个点,可以同时满足左侧和右侧以及只有一个点的情况。
因此,我们对每个颜色的点建一个 set ,排序规则采用dfn序从小到大,更新查找时使用二分即可,增加删除可以写在同一个函数里。对于求距离,使用倍增LCA即可。
初始时,将每个点都加一遍。
时间复杂度 \(O((n+m)\log n)\)
空间复杂度 \(O(n \log n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Graph {
struct edge {
int v, nxt;
};
int idx;
vector<int> h;
vector<edge> e;
Graph(int n = 0, int m = 0) { init(n, m); }
void init(int n, int m) {
idx = 0;
h.assign(n + 1, 0);
e.assign(m + 1, {});
}
void add(int u, int v) {
e[++idx] = { v,h[u] };
h[u] = idx;
}
};
const int N = 100007;
Graph g;
namespace LCA {
const int lgN = 16;
int dep[N], f[lgN + 7][N];
void dfs(int u, int fa = 0) {
f[0][u] = fa;
dep[u] = dep[fa] + 1;
for (int i = 1;i <= lgN;i++) f[i][u] = f[i - 1][f[i - 1][u]];
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v;
if (v == fa) continue;
dfs(v, u);
}
}
int LCA(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = lgN;i >= 0;i--) {
if (dep[f[i][u]] >= dep[v]) u = f[i][u];
if (u == v) return u;
}
for (int i = lgN;i >= 0;i--) {
if (f[i][u] != f[i][v]) {
u = f[i][u];
v = f[i][v];
}
}
return f[0][u];
}
int dis(int u, int v) { return dep[u] + dep[v] - 2 * dep[LCA(u, v)]; }
}
int dfncnt;
int rdfn[N];
void dfs(int u, int fa) {
rdfn[u] = ++dfncnt;
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v;
if (v == fa) continue;
dfs(v, u);
}
}
struct cmp {
bool operator()(int a, int b) const {
return rdfn[a] < rdfn[b];
}
};
int c[N];
set<int, cmp> st[N];
int ans[N];
void update(int x, int f) {
if (f == -1) st[c[x]].erase(x);
if (st[c[x]].size()) {
auto it = st[c[x]].lower_bound(x);
auto it1 = st[c[x]].begin();
auto it2 = prev(st[c[x]].end());
if (it != st[c[x]].begin() && it != st[c[x]].end()) {
it1 = it;
it2 = prev(it);
}
ans[c[x]] += f * (
LCA::dis(*it1, x)
+ LCA::dis(*it2, x)
- LCA::dis(*it1, *it2)
) / 2;
}
if (f == 1) st[c[x]].insert(x);
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
g.init(n, n << 1);
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g.add(u, v);
g.add(v, u);
}
dfs(1, 0);
LCA::dfs(1);
for (int i = 1;i <= n;i++)
cin >> c[i], update(i, 1);
int m;
cin >> m;
while (m--) {
char op;
cin >> op;
if (op == 'Q') {
int col;
cin >> col;
cout << (st[col].size() ? ans[col] : -1) << '\n';
}
else {
int x, col;
cin >> x >> col;
update(x, -1);
c[x] = col;
update(x, 1);
}
}
return 0;
}
NC200179 Colorful Tree的更多相关文章
- 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】
Colorful Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- AtCoder Beginner Contest 133 F Colorful Tree
Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- [HDU6793] Tokitsukaze and Colorful Tree
题目 又是一个条历新年,窗前的灼之花又盛开了. 时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了. 尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒. 灼之花的生命极为短暂,但它的花 ...
- Colorful tree
cnbb 我被数组清零卡了一天.. 子树改色询问子树颜色数.. 先考虑颜色为x的节点对祖先答案的贡献,那么我们考虑把所有这些节点都搞出来,按dfs序排序,然后考虑每个节点a掌管的祖先是它和按dfs序的 ...
- 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)
题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...
- HDU-6035:Colorful Tree(虚树+DP)
这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...
- ABC133F - Colorful Tree
ABC133FColorful Tree 题意 给定一颗边有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离. 数据都是1e5量级的. 思路 我自己一开始用树链 ...
- HDU6035 Colorful Tree
题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...
随机推荐
- idea新建spring boot 项目右键无package及java类的选项
新创建的spring boot项目,只有一个默认的资源目录及启动配置. 在 group 的目录下右键新建包路径时 ,发现没有package选项,也没有Java Class的选项: 解决办法: File ...
- Verilog仿真实践
Verilog必须掌握 逻辑仿真工具(VCS)和逻辑综合工具(DC) AndOR module AndOr( output X,Y, input A,B,C ); // A B进行按位与运算 assi ...
- 【C/C++】输出文件的相对路径
FILE 在有些编译器上会输出带路径的文件名,删除路径可使用函数 strrchr #include <string.h> #include <stdio.h> #define ...
- 有趣的Shell脚本学习
有趣的Shell脚本学习 倒计时脚本 #!/bin/bash echo 20秒倒计时开始: tput sc # 循环40秒 for count in `seq 0 20` do tput rc tpu ...
- [转帖]解决Java/MySQL性能问题的思路
https://plantegg.github.io/2023/08/28/%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98%E6%80%9D%E8%B7%AF/ 10年前写的 ...
- [转帖]LOAD DATA INFILE 导入数据
https://www.jianshu.com/p/bcafd8f3ad8e LOAD DATA INFILE语句用于高速地从一个文本文件中读取行,并写入一个表中.文件名称必须为一个文字字符串.LOA ...
- [转帖]netperf - 网络测试工具
1. 概述 Netperf是一种网络性能的测量工具,主要针对基于TCP或UDP的传输.Netperf根据应用的不同,可以进行不同模式的网络性能测试,即批量数据传输(bulk data transfer ...
- [转帖]RFC1180
[译] RFC 1180:朴素 TCP/IP 教程(1991) 译者序 本文翻译自 1991 年的一份 RFC(1180): A TCP/IP Tutorial. 本文虽距今将近 20 年,但内容并未 ...
- 六个节点三主三从Redis集群最简单搭建方法
背景 一个服务器上面的三主三从的界面太low,容易出问题. 为了验证高可用, 我这边使用六台机器进行了三主三从的搭建. 模仿开源版的一键搭建集群的脚本进行使用,感觉非常简单,这里简单进行一下总结. 环 ...
- Charles的基本使用
今天介绍Charles常用的几个功能 一.map local 1.map local是测试中mock数据常用的功能,首先我们选择需要mock数据的接口,这里以百度为例 抓包抓住该接口后鼠标右击选择ma ...