[bzoj5457]城市_dsu on tree
bzoj 5457 城市
题目大意
给定一棵以\(1\)为根的\(n\)个节点的有根树。
每个节点有一个民族和该民族在当前节点的人数。
有\(n\)个询问,第\(i\)个询问是求以\(i\)为根的子树内,人数最多的民族是哪个,这个民族有多少人。
如果最多的民族有多个输出编号最小的。
数据范围
\(1\le n\le 4\cdot 10^5\),\(m\le n\),\(1\le a_i\le m\),\(0\le b_i\le 1000\)。
题解
我们发现这个题满足一个性质,就是无修改、询问子树。
然后不难发现,这个题就是维护一个桶然后求编号最小的最大值,这东西显然可以合并啊。
好,无修改询问子树可合并,我们就考虑考虑\(dsu\ on\ tree\)。
想到\(dsu\ on\ tree\)这题就切掉了啊。
只需要维护一个每棵子树维护一个桶就好了。
代码
#include <bits/stdc++.h>
#define N 400010
using namespace std;
int to[N<<1],head[N],nxt[N<<1],tot;
int st[N],a[N],b[N],size[N],son[N],ans_num[N],ans_id[N];
int mx,id;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
inline void add(int x,int y) {to[++tot]=y; nxt[tot]=head[x]; head[x]=tot;}
void dfs1(int p,int fa)
{
size[p]=1;
for(int i=head[p];i;i=nxt[i]) if(to[i]!=fa)
{
dfs1(to[i],p);
size[p]+=size[to[i]];
if(size[to[i]]>size[son[p]]) son[p]=to[i];
}
}
void add(int p,int fa,int val)
{
st[a[p]]+=val*b[p];
if(st[a[p]]==mx&&a[p]<id) id=a[p];
else if(st[a[p]]>mx) mx=st[a[p]],id=a[p];
for(int i=head[p];i;i=nxt[i]) if(to[i]!=fa) add(to[i],p,val);
}
void dfs2(int p,int fa,int opt)
{
for(int i=head[p];i;i=nxt[i]) if(to[i]!=fa&&to[i]!=son[p]) dfs2(to[i],p,0);
if(son[p]) dfs2(son[p],p,1);
for(int i=head[p];i;i=nxt[i]) if(to[i]!=fa&&to[i]!=son[p]) add(to[i],p,1);
st[a[p]]+=b[p];
if(st[a[p]]==mx&&a[p]<id) id=a[p];
else if(st[a[p]]>mx) mx=st[a[p]],id=a[p];
ans_num[p]=mx,ans_id[p]=id;
if(!opt) add(p,fa,-1),mx=id=0;
}
int main()
{
int n=rd(),m=rd();
for(int i=1;i<n;i++) {int x=rd(),y=rd(); add(x,y),add(y,x);}
for(int i=1;i<=n;i++) a[i]=rd(),b[i]=rd();
dfs1(1,1); dfs2(1,1,1);
for(int i=1;i<=n;i++) printf("%d %d\n",ans_id[i],ans_num[i]);
return 0;
}
小结
\(dsu\ on\ tree\)的题目都有点小明显。
而且我们发现,这鬼东西是不是和点分治有点小像。
其实有些点分治题是完全可以拿这东西跑的。
算是黑科技吧,还是很好用的。
[bzoj5457]城市_dsu on tree的更多相关文章
- 【BZOJ】3091: 城市旅行 Link-Cut Tree
[题意]参考PoPoQQQ. 给定一棵树,每个点有一个点权,提供四种操作: 1.删除两点之间的连边 不存在边则无视 2.在两点之前连接一条边 两点已经联通则无视 3.在两点之间的路径上所有点的点权加上 ...
- bzoj5457 城市
一棵树,每个点有一个民族,和一个人数,求每个子树里最多的民族及其人数,如果一样,输出编号最小的 $n \leq 500000$ sol: 卡莫队的毒瘤题,需要 dsu on tree 大概就是 dfs ...
- 2019.01.19 bzoj5457: 城市(线段树合并)
传送门 线段树合并菜题. 题意简述:给一棵树,每个节点有bib_ibi个aia_iai民族的人,问对于每棵子树,子树中哪个民族的人最多,有多少人. 思路: 直接上线段树合并,边合并边维护答案即可. ...
- dsu on tree(无讲解)
CF741D. Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 分析: 最多有一个字符出现奇数次 维护某个状态下深度的最大值,注意 ...
- P5471- K-D tree优化建图-弹跳
P5471- K-D tree优化建图-弹跳 优化建图是一种思想. 题意 有\(n\)个城市分布在小鸟岛上,有\(m\)个弹弓分布在这些城市里.因为弹弓体积大,固定麻烦,所以每个弹弓只能把小鸟弹飞到一 ...
- Hibernate 基础配置及常用功能(二)
本章主要是描述几种经典映射关系,顺带比较Hibernate4.x和Hibernate5.x之间的区别. 一.建立测试工程目录 有关实体类之间的相互映射关系,Hibernate官方文档其实描述的非常详细 ...
- 070.Python聚焦爬虫数据解析
一 聚焦爬虫数据解析 1.1 基本介绍 聚焦爬虫的编码流程 指定url 基于requests模块发起请求 获取响应对象中的数据 数据解析 进行持久化存储 如何实现数据解析 三种数据解析方式 正则表达式 ...
- 【BZOJ5457】城市(线段树合并)
点此看题面 大致题意: 一棵树上每个点有颜色\(a_i\)和权值\(b_i\),求以每个点为根的子树内权值和最大的颜色及其权值和. 线段树合并 这是一道线段树合并板子题. (关于线段树合并,可参考我的 ...
- [BZOJ3754]Tree之最小方差树
3754: Tree之最小方差树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 402 Solved: 152[Submit][Status][Di ...
随机推荐
- python之dic {字典}(重要指数*****)
1. 什么是字典 {'name': '汪峰', 'age': 18} '键':'值' 别的语言键值对数据 键: 必须是可哈希(不可变的数据类型),并且是唯一的 值: 任意 可以保存任意类型的数据 字典 ...
- 打印两个有序链表的公共部分 【题目】 给定两个有序链表的头指针head1和head2,打印两个 链表的公共部分
简单题 package my_basic.class_3; public class Code_10_PrintCommonPart { public static class Node{ int v ...
- shell脚本,awk实现文件a的每行数据与文件b的相对应的行的值相减,得到其绝对值。
解题思路 文件 shu 是下面这样的.220 34 50 70553 556 32 211 1 14 98 33 文件 jian是下面这样的.1082 想要得到结果是下面这样的.210 24 40 6 ...
- Swift 编程思想 Part 4:map all the things!
Swift 编程思想 Part 4:map all the things! 2015-10-22 837 文章目录 1. 数组 vs. 可选类型 2. 作用在可选类型上的 map() 3. 回到我们 ...
- Luogu P2123 皇后游戏(贪心)
题目链接:P2123 皇后游戏 如果证明这个题为什么是贪心的话,我是不会的,但是一看这个题目就是一个贪心,然后满足贪心的性质: 都能从两个人(东西)扩展到n个人(东西) 一定能从相邻状态扩展到不相邻的 ...
- POJ-3669-流星雨
这题的话,卡了有两个小时左右,首先更新地图的时候越界了,我们进行更新的时候,要判断一下是不是小于零了,越界就会Runtime Error. 然后bfs 的时候,我没有允许它搜出300以外的范围,然后就 ...
- HDU-1009-肥鼠交易
这题是一道简单的可拆分的贪心题目,需要注意的是,我们定义的结构体里面都应该用double类型, 或者float类型,不然两个int相除,就失去了精度(强转也可以). #include <cstd ...
- 【php】 给数组重建索引
array_values $a = [1,2]; unset($a[1]); $a[] = 3; print_r($a); // 输出 [0=>1,2=>3]
- mysql函数总结
MySQL函数 MySQL数据库提供了很多函数包括: 数学函数:字符串函数:日期和时间函数:条件判断函数:系统信息函数:加密函数:格式化函数: 一.数学函数 数学函数主要用于处理数字,包括整型.浮点数 ...
- 日志logging
日志: 日志分为5个级别:debug(10),info(20),warning(30),error(40),critical(50) 日志四个组成部分:logger,handler,filter,fo ...