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. Eclipse下载安装并运行第一个Hello world(详细)

    Eclipse下载安装并运行第一个Hello world(详细) 1.下载安装和配置JDK JDK详细的安装教程参考:https://www.cnblogs.com/mxxbc/p/11845150. ...

  2. 201871010114-李岩松《面向对象程序设计(java)》第一周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...

  3. Jetpack Compse 实战 —— 全新的开发体验

    公众号回复 Compose 获取安装包 项目地址: Wanandroid-Compose 经过前段时间的 Android Dev Summit ,相信你已经大概了解了 Jetpack Compose ...

  4. mysql 创建用户及授权(2)

    一. MySQL初始密码 新安装的MySQL默认是没有密码的,设置初始密码可以用以下命 mysqladmin -u root password 'new-password' mysqladmin -u ...

  5. hdu 2063 过山车 (二分图,最大匹配)

    过山车Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  6. 力扣(LeetCode)验证回文字符串II 个人题解

    给定一个非空字符串 s,最多删除一个字符.判断是否能成为回文字符串. 示例 1: 输入: "aba" 输出: True 示例 2: 输入: "abca" 输出: ...

  7. 从静态代理,jdk动态代理到cglib动态代理-一文搞懂代理模式

    从代理模式到动态代理 代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂.本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现.读完本文你将get到以下几点: 为什么需要 ...

  8. Docker基础与实战,看这一篇就够了

    docker 基础 什么是Docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Uni ...

  9. js 关于apply和call的理解使用

    关于call和apply,以前也思考良久,很多时候都以为记住了,但是,我太难了.今天我特地写下笔记,希望可以完全掌握这个东西,也希望可以帮助到任何想对学习这个东西的同学. 一.apply函数定义与理解 ...

  10. 护网杯一道crypto

    import os def xor(a,b): assert len(a)==len(b) c="" for i in range(len(a)): c+=chr(ord(a[i] ...