csu1811(树上启发式合并)
csu1811
题意
给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集。
分析
转化一下,即所求答案为每次删掉 \(u\) 和 \(u\) 的父亲节点所连的边后形成的两颗子树的颜色集合的交集。
那么我们要求的其实和 \(u\) 的子树有关。子树的状态(颜色数量信息)是可以复用的。
可以套用 树上启发式合并 ,固定 1 为根节点,从上往下搜,每次保留子节点中节点最多的那颗子树的状态(颜色数量信息),也就是在计算当前节点所在子树的节点颜色的时候跳过这个子节点(因为前面保留了)。复杂度优化到 \(O(nlogn)\)。
code
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n;
int fa[MAXN], son[MAXN], dep[MAXN], siz[MAXN];
int col[MAXN];
int cnt, head[MAXN];
struct Edge {
int to, next;
} e[MAXN << 1];
void addedge(int u, int v) {
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u) {
siz[u] = 1;
son[u] = 0;
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u]) {
fa[e[i].to] = u;
dep[e[i].to] = dep[u] + 1;
dfs(e[i].to);
if(siz[e[i].to] > siz[son[u]]) son[u] = e[i].to;
siz[u] += siz[e[i].to];
}
}
}
int COL[MAXN]; // 表示所有颜色的数量
int vis[MAXN];
int same; // 当前子树的颜色和另一个子树的颜色集合的交集
int C[MAXN]; // 当前子树某个颜色的数量
int ans[MAXN]; // ans[u]: 表示删掉 u 和它父亲所连的边后形成的两颗子树的答案
void update(int u, int c) {
C[col[u]] += c;
if(c > 0 && COL[col[u]] > 1) {
if(C[col[u]] == 1) same++;
else if(C[col[u]] == 0 || C[col[u]] == COL[col[u]]) same--;
}
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u] && !vis[e[i].to]) update(e[i].to, c);
}
}
void dfs1(int u, int flg) {
for(int i = head[u]; ~i; i = e[i].next) {
if(e[i].to != fa[u] && e[i].to != son[u]) dfs1(e[i].to, 1);
}
if(son[u]) {
dfs1(son[u], 0);
vis[son[u]] = 1;
}
update(u, 1);
ans[u] = same;
if(son[u]) vis[son[u]] = 0;
if(flg) {
update(u, -1);
same = 0;
}
}
typedef pair<int, int> P;
map<P, int> mp;
int res[MAXN];
int main() {
while(~scanf("%d", &n)) {
mp.clear();
cnt = 0;
dep[1] = 1;
fa[1] = 1;
memset(head, -1, sizeof head);
memset(COL, 0, sizeof COL);
memset(C, 0, sizeof C);
memset(vis, 0, sizeof vis);
same = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &col[i]);
COL[col[i]]++;
}
for(int i = 1; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
mp[P(x, y)] = mp[P(y, x)] = i;
addedge(x, y);
addedge(y, x);
}
dfs(1);
dfs1(1, -1);
for(int i = 2; i <= n; i++) {
res[mp[P(i, fa[i])]] = ans[i];
}
for(int i = 1; i < n; i++) {
printf("%d\n", res[i]);
}
}
return 0;
}
csu1811(树上启发式合并)的更多相关文章
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- hdu6191(树上启发式合并)
hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到 ...
- Codeforces 208E - Blood Cousins(树上启发式合并)
208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...
- 【CodeChef EDGEST】Edges in Spanning Trees(树链剖分+树上启发式合并)
点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e ...
- [Codeforces600E] Lomsat gelral(树上启发式合并)
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...
随机推荐
- android surfaceview 入门介绍
由于工作中需自定义控件,以前没写过. 开始时,实用view 实现了,经理说不好,担心效率低,要求每秒需要刷新10次左右. 然后,学习使用 surfaceview. 看了网上简单的Demo,找到him ...
- Python调用Webservice
使用Python调用webservice 推荐使用 suds包 该包一般在Python2.x python3各种麻烦 略过 实例 import suds # webservice url url ...
- 牛客网暑期ACM多校训练营(第一场):D-Two Graphs
链接:D-Two Graphs 题意:给出图G1和G2,求G2的子图中和G1同构的个数. 题解:只有8个点,暴力枚举G2的点每个排列,让G1映射到G2中,求出同构个数a.同构的G2就是在G1有边的对应 ...
- HeidiSQL安装和使用教程
HeidiSQL 是一个功能非常强大的 MySQL 客户端软件,我们通过它来操作MySQL数据库,比直接通过命令行工具操作要简单的多.我们使用HidiSQL来连接MySQL数据库,MySQL数据库的安 ...
- 清除浮动float (:after方法)
1. 什么时候需要清除浮动?清除浮动有哪些方法? (1)对元素进行了浮动(float)后,该元素就会脱离文档流,浮动在文档之上.在CSS中,任何元素都可以浮动.浮动元素会生成一个块级框,而不论它本身是 ...
- Centos安装后的一些必要处理工作
1永久关闭selinux,修改成permissive或者disabled(建议),修改完需重启 2配置network 3.禁止ping(可选,一般不需要禁止)(默认为0位启用ICMP协议,1为禁止), ...
- BZOJ1023[SHOI2008]cactus仙人掌图 【仙人掌DP】
题目 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌 图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路. 举例来说 ...
- 当鼠标点击input框时,想让全选input框的所有内容只需要加“onfocus="this.select();”就可以了
当鼠标点击input框时,想让全选input框的所有内容只需要加“onfocus="this.select();”就可以了
- CI的model层的操作
1.需求 整理ci框架下model层的相关操作 2.代码 model的代码,放在application/model目录下,文件名为Coupon.php <?php class Coupon ex ...
- PAT L1 049 天梯赛座位分配
天梯赛每年有大量参赛队员,要保证同一所学校的所有队员都不能相邻,分配座位就成为一件比较麻烦的事情.为此我们制定如下策略:假设某赛场有 N 所学校参赛,第 i 所学校有 M[i] 支队伍,每队 10 位 ...