Bobo has a tree with n vertices numbered by 1,2,…,n and (n-1) edges. The i-th vertex has color c i, and the i-th edge connects vertices a i and b i.
Let C(x,y) denotes the set of colors in subtree rooted at vertex x deleting edge (x,y).
Bobo would like to know R_i which is the size of intersection of C(a i,b i) and C(bi,a i) for all 1≤i≤(n-1). (i.e. |C(a i,b i)∩C(b i,a i)|)

Input

The input contains at most 15 sets. For each set:
The first line contains an integer n (2≤n≤10 5).
The second line contains n integers c 1,c 2,…,c n (1≤c_i≤n).
The i-th of the last (n-1) lines contains 2 integers a i,b i (1≤a i,b i≤n).

OutputFor each set, (n-1) integers R 1,R 2,…,R n-1.Sample Input

4
1 2 2 1
1 2
2 3
3 4
5
1 1 2 1 2
1 3
2 3
3 5
4 5

Sample Output

1
2
1
1
1
2
1

Hint

题解:题意就是,给以一颗树n个节点,每个节点有一种颜色,然年后对于n-1条边,如果把一条边截断,让你求两颗子树有多少种相同的颜色,依次输入每一条边的答案。

启发式搜索,分别记录点和边的答案;如果点u和其子树某种颜色的数量已经等于总量了,那么对于该子树外的一部分,就没有该中颜色了,答案-1;如果小于总量,答案+1;

然后更新u节点该颜色的数量即可;

参考代码:

 #include<bits/stdc++.h>
using namespace std;
#define clr(a,val) memset(a,val,sizeof (a))
#define pb push_back
#define fi first
#define se second
typedef long long ll;
const int maxn=1e5+;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-') f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
struct Edge{
int to,index,nxt;
} edge[maxn<<];
int n,head[maxn<<],tot;
int col[maxn],sum[maxn],ans[maxn],res[maxn<<];//ans[u]表示u点及子节点的答案, res[edge]表示边的答案
map<int,int> cnt[maxn];//cnt[u][color] 表示u点子树color颜色有多少个节点 inline void Init()
{
clr(head,-);clr(sum,); tot=;
for(int i=;i<=n;++i) cnt[i].clear();
} inline void addedge(int u,int v,int id)
{
edge[tot].to=v;
edge[tot].index=id;
edge[tot].nxt=head[u];
head[u]=tot++;
} inline void dfs(int u,int fa,int id)
{
cnt[u][col[u]]=;
ans[u] = cnt[u][col[u]]<sum[col[u]]?:;
for(int e=head[u];~e;e=edge[e].nxt)
{
int v=edge[e].to;
if(v==fa) continue;
dfs(v,u,edge[e].index);
if(cnt[u].size()<cnt[v].size())
{
swap(cnt[u],cnt[v]);
swap(ans[u],ans[v]);
}
map<int,int>::iterator it;
for(it=cnt[v].begin();it!=cnt[v].end();it++)
{
if(!cnt[u][(*it).fi] && (*it).se<sum[(*it).fi]) ++ans[u];
else if(cnt[u][(*it).fi] && cnt[u][(*it).fi]+(*it).se==sum[(*it).fi]) --ans[u];
cnt[u][(*it).fi]+=(*it).se;//加上子树的数量
}
}
res[id]=ans[u];
} int main()
{
while(~scanf("%d",&n))
{
Init();
for(int i=;i<=n;++i) col[i]=read(),sum[col[i]]++;
for(int i=;i<n;++i)
{
int u=read(),v=read();
addedge(u,v,i);addedge(v,u,i);
}
dfs(,,);
for(int i=;i<n;++i) printf("%d\n",res[i]);
} return ;
}

CSUOJ1811 Tree Intersection (启发式合并)的更多相关文章

  1. csu oj 1811: Tree Intersection (启发式合并)

    题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1811 给你一棵树,每个节点有一个颜色.问删除一条边形成两棵子树,两棵子树有多少种颜色是有 ...

  2. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  3. dsu on tree[树上启发式合并学习笔记]

    dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有 ...

  4. dsu on tree (树上启发式合并) 详解

    一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

  5. AGC 014E.Blue and Red Tree(思路 启发式合并)

    题目链接 \(Description\) 给定两棵\(n\)个点的树,分别是由\(n-1\)条蓝边和\(n-1\)条红边组成的树.求\(n-1\)次操作后,能否把蓝树变成红树. 每次操作是,选择当前树 ...

  6. dsu on tree(树上启发式合并)

    简介 对于一颗静态树,O(nlogn)时间内处理子树的统计问题.是一种优雅的暴力. 算法思想 很显然,朴素做法下,对于每颗子树对其进行统计的时间复杂度是平方级别的.考虑对树进行一个重链剖分.虽然都基于 ...

  7. CSU 1811: Tree Intersection(线段树启发式合并||map启发式合并)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1811 题意:给出一棵树,每一个结点有一个颜色,然后依次删除树边,问每次删除树边之后,分开的两个 ...

  8. codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(启发式合并)

    codeforces 741D Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题意 给出一棵树,每条边上有一个字符,字符集大小只 ...

  9. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

随机推荐

  1. 小白学 Python(23):Excel 基础操作(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  2. 【algo&ds】1.时间复杂度和空间复杂度分析

    1.时间复杂度分析O(f(n)) 分析方法 只关注循环执行次数最多的一段代码 加法原则 乘法原则 高优先级原则 常见时间复杂度量级 多项式量级和非多项式量级.其中,非多项式量级只有两个:O(2^n) ...

  3. PageHelper分页+排序

    使用pageHelper插件来分页,只需在执行sql前用即可 String orderBy = 排序字段 + " desc";//按照(数据库)排序字段 倒序 排序 PageHel ...

  4. Grid表格的js触发事件

    没怎么接触过Grid插件: 解决的问题是:点击Grid表行里的内容触发js方法弹出模态框,用以显示选中内容的详细信息. 思路:给准备要触发的列加上一个css属性,通过这个css属性来获取元素并触发js ...

  5. 无法优化的O(n!) 算法

    旅行商问题: 有一位旅行商,他需要前往5个城市. 要前往这5个城市,同时要确保旅程最短. 对于每种顺序,他都计算总旅程,再挑选出旅程最短的路线.5个城市有120种不同的排列方式.因此,在涉及5个城市时 ...

  6. PostGIS mysql_fdw使用(Linux)

    ##前文讲了mysql_fdw的安装,此文主要讲mysql_fdw的配置以及使用 ##附上前文链接:https://www.cnblogs.com/giser-s/p/11208803.html 背景 ...

  7. C语言之路

    C 简介 C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的.C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现. 在 1978 ...

  8. 2019-11-5:docker拉去配置oracle数据库

    转载自:https://www.cnblogs.com/OliverQin/p/9765808.html 1.拉取Oracle11g镜像 docker pull registry.cn-hangzho ...

  9. linux工作调度(计划任务)

    linux工作调度有两种:at,cron · at:at是一个可以处理仅执行一次就结束调度的命令.说白了就是在某个时间需要干某一件事,例如在2018年10月12日下午一点要执行一个数据库矫正脚本. · ...

  10. 【python测试开发栈】—python内存管理机制(二)—垃圾回收

    在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...