set 容器详解 附大根堆题解
PART 1 set
什么是 set

——来源cppreference
简言之,它就是一种存进去就可以自动按升序排列的特殊容器,通常的 set 还具有自动去重的功能。
定义方式:
std::set<int>s;
'set'+<存储数据类型>+容器名
注意的是,这里存储数据类型不仅包含常用的int,long long,double等数值类,也可以是char,string这些字符类的,排序标准为字典序(强者处处是惊喜)。
怎么使用 set
首先,我们要了解几个 set 的常用函数:
指针类
s.begin()//指向 s 的起始
s.end()//指向 s 的末尾
容量类
s.empty()//检查容器是否为空
s.size()//返回元素数(返回值类型为 unsigned int )
修改类
s.insert(w)//向容器中插入 w 这个元素
s.erase(w)//在容器中删除 w 这个元素
s.clear()//将 s 清空
swap(s1,s2)//交换 s1 与 s2 两个容器内的元素
查找类
s.find(w)//在容器中查找 w 这个元素所在的**地址**
//若不存在该元素,则返回 s.end()
s.lower_bound(w)//在容器中寻找第一个不小于 w 的元素**地址**
//若不存在则返回 s.end()
我们可以观察到,很多 set 的返回值类型都是特殊的,因此还存在一个迭代器set<int>::iterator,它是一个指向 set<int> 中元素的指针,可以通过迭代器访问 set<int> 中的元素,并能够进行迭代器运算,如自增等操作。
我们在调用 s 中的值的时候,可以如下操作:
输出 s 中的所有值
set<int>::iterator it;
for(it=s.begin();it!=s.end();it++)
cout<<*it<<' ';// *it 是获取当前迭代器指向的元素的值
自 c++11 引入了类型 auto 后,我们可以更加简便地完成上面的操作。
for(auto it:s)
cout<<it<<' ';//这里 auto 的类型等同于我们定义 s 时的数据类型,也就是 int
set 和 multiset
multiset 在 cppreference 中定义如下:

简言之, multiset 的特性有:
- 可以保留重复的元素,也就是没有自动去重的性质。
- multiset 支持插入、删除和查找操作的平均时间复杂度均为 \(O(log\,n)\),而 set 只支持插入和查找操作的平均时间复杂度为 \(O(log\,n)\),删除操作的平均时间复杂度为 \(O(1)\)。
- multiset 在删除时只会删除元素值相同的元素中的一个,而不是全部删除或删除一些。
通常情况下,我们多使用 set ,因为它在进行查找等操作时更快;而只有在需要保留重复元素的少数情况下,我们使用 multiset ,下题就是一个例子。
PART 2 大根堆
题面

思路
常规办法为线段树合并,但太长了不想写 但总感觉有更优的做法,所以就有了下面基于 set 优化的 dfs 做法。
我们可以通过 dp 引入,固定一点作为根结点,用f[u][i]表示以 \(u\) 为树根的子树里结点权值小于 \(i\) 的个数,其中 \(i\le v_u\);用 \(size_u\) 表示以 \(u\) 为根的树的大小。
那么很容易能想到状态转移方程为:
\]
\]
那么如何存储? multiset !
set 自带的查找功能可以很方便的判断条件是否成立, \(size\) 函数也直接提供了上述 \(size\) 数组。
使用 dfs 进行遍历,由子结点逐个回溯至根节点,最后根节点的 \(size\) ,即为答案。
代码中加入了部分注释,供参考。
code:
#include<bits/stdc++.h>
inline int qr()
{
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
#define qr qr()
using namespace std;
const int Ratio=0;
const int N=500005;
int n,cnt;
int va[N],hh[N],to[N],ne[N];
multiset<int>f[N];
namespace Wisadel
{
void Wadd(int u,int v)
{//加边
to[++cnt]=v;
ne[cnt]=hh[u];
hh[u]=cnt;
}
void Wdfs(int u,int fa)
{
for(int i=hh[u];i!=-1;i=ne[i])
{//遍历
int t=to[i];
if(t==fa)
continue;
Wdfs(t,u);
if(f[u].size()<f[t].size())
swap(f[u],f[t]);
//大根堆,所以父节点的子树和应大于子节点
for(auto j:f[t])
f[u].insert(j);
//类似线段树合并 将两棵树并到一起
f[t].clear();
//擦去被合并了的树
}
if(f[u].size()>0&&f[u].lower_bound(va[u])!=f[u].end())
f[u].erase(f[u].lower_bound(va[u]));
//因为是大根堆,所以子应小于父
//那么若存在比父大的元素,这个堆便不成立
//擦去它
f[u].insert(va[u]);
//把当前结点(根节点)插入
}
short main()
{
memset(hh,-1,sizeof hh);
n=qr;
for(int i=1;i<=n;i++)
{
va[i]=qr;int b=qr;
if(i!=1)
Wadd(i,b),Wadd(b,i);
}
Wdfs(1,-1);
printf("%d\n",(int)f[1].size());
//我们所用dfs的遍历形式,保证了会先将尽头的子树遍历尽
//所以每个结点遍历后的结果,是包含了它以及它子树的最优解
//所以经过交换,最后答案会体现在f[1]容器内元素的个数
return Ratio;
}
}
int main(){return Wisadel::main();}
完结撒花~

set 容器详解 附大根堆题解的更多相关文章
- 最小割树(Gomory-Hu Tree)求无向图最小割详解 附 BZOJ2229,BZOJ4519题解
最小割树(Gomory-Hu Tree) 前置知识 Gomory-Hu Tree是用来解决无向图最小割的问题的,所以我们需要了解无向图最小割的定义 和有向图类似,无向图上两点(x,y)的割定义为一个边 ...
- linux管道命令grep命令参数及用法详解---附使用案例|grep
功能说明:查找文件里符合条件的字符串. 语 法:grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>] ...
- [Spring学习笔记 1 ] Spring 简介,初步知识--Ioc容器详解 基本原理。
一.Spring Ioc容器详解(1) 20131105 1.一切都是Bean Bean可是一个字符串或者是数字,一般是一些业务组件. 粒度一般比较粗. 2.Bean的名称 xml配置文件中,id属性 ...
- C++ STL bitset 容器详解
C++ STL bitset 容器详解 本篇随笔讲解\(C++STL\)中\(bitset\)容器的用法及常见使用技巧. \(bitset\)容器概论 \(bitset\)容器其实就是个\(01\)串 ...
- 跟我一起学STL(2)——vector容器详解
一.引言 在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多.然而容器又可以序列式容器和关联 ...
- Java 序列化Serializable详解(附详细例子)
Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是 ...
- 2.3 C++STL vector容器详解
文章目录 2.3.1 引入 2.3.2 代码实例 2.3.3 运行结果 总结 2.3.1 引入 vector 容器 动态数组 可变数组 vector容器 单口容器(尾部操作效率高) vector动态增 ...
- Windows WMIC命令使用详解(附实例)
第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符.在WMIC命令行提示符上,命令以交互的方式执行 执行“wmic”命令启动WMIC命令行环境.这个命令可以在 ...
- SILC超像素分割算法详解(附Python代码)
SILC算法详解 一.原理介绍 SLIC算法是simple linear iterative cluster的简称,该算法用来生成超像素(superpixel) 算法步骤: 已知一副图像大小M*N,可 ...
- [No000013A]Windows WMIC命令使用详解(附实例)
第一次执行WMIC命令时,Windows首先要安装WMIC,然后显示出WMIC的命令行提示符.在WMIC命令行提示符上,命令以交互的方式执行 执行“wmic”命令启动WMIC命令行环境.这个命令可以在 ...
随机推荐
- 利用 🤗 Optimum Intel 和 fastRAG 在 CPU 上优化文本嵌入
嵌入模型在很多场合都有广泛应用,如检索.重排.聚类以及分类.近年来,研究界在嵌入模型领域取得了很大的进展,这些进展大大提高了基于语义的应用的竞争力.BGE.GTE 以及 E5 等模型在 MTEB 基准 ...
- [Unity] 为什么文件名和类名需要相同
挂载脚本时文件名和类名的关联方式 写过Unity脚本的人应该都知道,挂载脚本的文件名和类名必须相同 今天写新功能的时候偶然发现了这个规则的底层逻辑 并且发现这个规则并非必须的,实际上Unity是根据脚 ...
- 5 更换npm为国内镜像
更改npm为国内镜像 在终端执行. npm set registry http://registry.npmmirror.com 首先, 打开"我的电脑". 找到"c盘中 ...
- #状压dp,拓扑排序,内向基环树#CF1242C Sum Balance
题目 有 \(k\) 个盒子, 第 \(i\) 个盒子有 \(n_i\) 个数. 保证所有数互不相同. 从每个盒子各拿出一个数, 并按照某种顺序放回去(每个盒子恰好放入一个数). 判断是否能使操作后所 ...
- 如何在现实场景中随心放置AR虚拟对象?
随着AR的发展和电子设备的普及,人们在生活中使用AR技术的门槛降低,比如对于不方便测量的物体使用AR测量,方便又准确:遇到陌生的路段使用AR导航,清楚又便捷:网购时拿不准的物品使用AR购物,体验更逼真 ...
- centos环境Jenkins配置war包Tomcat
末尾有软件安装包,自行下载(centos环境) centos JDK Jenkins maven tomcat git myslq nginx 7.9 11.0.19 2.418 3.8.1 9.0. ...
- 照骗qsnctfwp
题目附件 使用 010 Editor 等工具打开发现 flag.txt 字样 将图片保存至 Kali 使用工具 foremost,通过命令foremost 3.png即可分离处图片所含隐写文件 打开发 ...
- centos8 \CentOS 9 Stream \Oracle Linux8\Oracle Linux 9 rpm 安装mysql8.0.28 mysql8.0.34
centos8 rpm 安装mysql8.0.28 检查 检测系统是否自带安装 MySQL 命令如下: rpm -qa | grep mysql 如果如下存在已安装的包,就需要卸载 mysql80-c ...
- 用存储过程和 JAVA 写报表数据源有什么弊端?
我们在报表开发中经常会使用存储过程准备数据,存储过程支持分步计算,可以实现非常复杂的计算逻辑,为报表开发带来便利.所以,报表开发中这样的存储过程并不少见: 3008 行,141KB 的存储过程,会给报 ...
- 重新整理数据结构与算法(c#)——算法套路迪杰斯特拉算法[三十一]
前言 迪杰斯特拉算法 是求最短路径方法的其中一种,这个有什么作用呢? 有一张图: 假设求G点到其他各点的最小路径. 是这样来的. 比如找到了和G点相连接所有点,ABED.这时候确定GA是一定是最短的, ...
