multiset usage as heap

本文介绍了一种利用两个堆(大顶堆和小顶堆)的数据结构来动态维护序列中位数的方法。通过不断调整两个堆之间的平衡,确保任何时候都能快速获取到当前序列的中位数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Middle number

There is a sequence of integers, we have two operations now

1 add a: means add an integer a to the end of the sequence, forms a N+1 long sequence.

2 mid : Output the current sequence's middle numbera sequence's middle number is the middle position of the sequence when it's sorted by in creasing order.(if the sequence's length is even, then the middle position is the litter number's position of the two middle numbers)

example 1, sequence 1 2 13 14 15 16 and it's middle number is 13

example 2, sequence 1 3 5 7 10 11 17 and it's middle number is 7

example 3, 1 1 1 2 3 and it's middle number is 1

Input

The first line of the input gives the number of test cases T, for each test case the first line is the sequence's inital length N, the second line has N number represent the integer sequence. then third line is the operation number M then follows M lines, each line has the format either add a or mid (1<=N<=100000, 0<=M<=10000)

Output

each test case for each mid operation output the middle number

Sample Input

 1
6
1 2 13 14 15 16
5
add 5
add 3
mid
add 20
mid
Sample Output

 5
13
题目分析:数据结构题,使用一个大顶堆与一个小顶堆,时刻维护着大顶堆的元素小于小顶堆元素,并且大顶堆内元素的个与小顶内元素的个数相等或者比后者多一个,故每次查寻的结果都是大顶堆顶元素
n用STL实现堆操作

 

#include<iostream>
#include<set>
using namespace std;

multiset <int> small;
multiset <int, greater<int> > big;


int main()
{
        int cas;
        scanf("%d",&cas);
        while(cas--){
            int n,num;
            scanf("%d",&n);
            small.clear();
            big.clear();
            int nt = n;
            while(nt--){
                scanf("%d",&num);
                small.insert(num);
            }
            for(int i = 0; i < (n+1)/2; i++){
                big.insert(*(small.begin()));
                small.erase(small.begin());
            }
            int m;
            scanf("%d",&m);//getchar();
            char op[100];
            while(m--){
                scanf("%s",&op);
                if(!strcmp(op, "add"))
                {
                    scanf("%d",&num);
                    if(num > *big.begin()){
                        small.insert(num);
                    }
                    else
                    big.insert(num);
                    if(small.size() > big.size()){
                        big.insert(*small.begin());
                        small.erase(small.begin());
                    }
                    else if(big.size() > small.size() + 1){
                        small.insert(*big.begin());
                        big.erase(big.begin());
                    }
                }
                else
                printf("%d\n",*(big.begin()));
            }
        }
        return 0;
}

 

### Multiset 数据结构实现和用法 #### 定义与特性 `std::multiset` 是 C++ 标准模板库 (STL) 提供的一种关联容器,其内部采用红黑树(一种自平衡二叉查找树)作为底层数据结构[^2]。这种设计确保了 `multiset` 能够高效地支持插入、删除以及查找操作。 #### 关键属性 - **允许重复元素**:不同于 `set` 只能保存唯一值,`multiset` 支持同一数值多次出现。 - **自动排序功能**:所有成员函数均保持集合有序排列,默认按升序组织;可通过定制比较器改变顺序逻辑。 #### 自定义类型的支持 对于复杂的数据类型如结构体或类对象,为了能够在 `multiset` 中正常工作并维持特定次序关系,需重载小于运算符 (`<`) 或者提供外部比较谓词给定构造参数。例如,在给出的例子中: ```cpp struct rec { int x, y; }; struct cmp { bool operator()(const rec& a, const rec& b) const { return a.x < b.x || (a.x == b.x && a.y < b.y); } }; ``` 这里定义了一个名为 `rec` 的简单记录类型及其对应的比较规则 `cmp`,之后可以创建基于此类型的多集实例: ```cpp #include <set> // ... multiset<rec, cmp> h; ``` 上述代码片段展示了如何利用用户定义的比较方式初始化一个多集中存储 `rec` 类型的对象,并依据指定条件进行排序[^1]。 #### 基本操作方法概览 - 插入新项:使用 `insert()` 成员函数向容器添加元素; - 删除现有条目:调用 `erase()` 方法移除单个或者全部匹配项; - 查找目标位置:借助迭代器遍历访问各节点,亦可运用 `find()` 函数快速定位某关键字所在之处; - 获取大小统计:通过 `size()` 查询当前容纳了多少实体单元。 综上所述,`multiset` 不仅继承了标准关联容器的优势特点&mdash;&mdash;即高效的检索性能及稳定的内存管理机制,还进一步放宽了关于唯一性的约束限制,使之成为处理含有冗余信息场景下的理想选择之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值