zoukankan      html  css  js  c++  java
  • [data structure]应用堆解决Medium Value询问问题

    QUQ摸鱼几个月之后…马上就要各种比赛来了,赶紧爬起来干正事了qwq

    先给出题面

    Medium

    You should write a program to handle some operations on an initially empty array.

    Input Specification:

    The first line contains an integer n (1n105​​) indicating the number of operations.

    Each of the following n lines contains a kind of operation:

    • 1 x : to add an integer x into the array
    • 2 : to output the medium value of the array

    Output Specification:

    For each operation 2 , output the value rounded to one decimal place in a line.

    时限 100ms

    简而言之,题目要求维护一个序列,能够向其中添加新的元素&求得中位数

    一个非常容易想到的思路是,每次加入元素时保持序列有序,这样可以非常容易的取得中位数

    但是插入数字的复杂度是O(n),1e5的数据规模&100ms的时限 肯定没法用平方复杂度跑过去(加之还要二分找位置,更加不可能跑过去了。)

    so…我们可以从中位数的独特性质入手

    在一个有序序列中,如果size为奇数,则中间一位数则为中位数

    否则取中间两位数的平均数

    也就是说,我们不需要关心除了中间一个/两个数之外的其他数字的位置情况

    换个角度想,也就是说,我们只需要关心序列前一半的最大值,序列后一半的最小值且我们只想知道这两个数的值。

    则可以考虑将序列一分为二,建两个堆,最大堆&最小堆,保持两个堆的元素个数总是相同或者相差1

    同时维持最大堆的堆顶元素总是小于等于最小堆的堆顶元素(即模拟序列左半边和右半边的情况,以达到可以随时询问medium value的目的,同时加入元素只需要对数复杂度)

    差不多就是这个思路了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n, op, t;
    priority_queue<int> maxheap;
    priority_queue<int, vector<int>, greater<int> > minheap;
    
    int main(){
        cin>>n;
        while(n--){
            scanf("%d", &op);
            if(op == 1){
                scanf("%d", &t);
                if(!maxheap.size() && !minheap.size()) maxheap.push(t);
                else if(maxheap.size() == minheap.size()){
                    if(maxheap.top() > t) maxheap.push(t);
                    else minheap.push(t);
                }
                else{
                    if(maxheap.size() > minheap.size()){
                        if(maxheap.top() > t){
                            minheap.push(maxheap.top());
                            maxheap.pop();
                            maxheap.push(t);
                        }
                        else{
                            minheap.push(t);
                        }
                    }
                    else{
                        if(minheap.top() < t){
                            maxheap.push(minheap.top());
                            minheap.pop();
                            minheap.push(t);
                        }
                        else maxheap.push(t);
                    }
                }
            }
            else if(op == 2){
                if(maxheap.size() == minheap.size())
                    printf("%.1f
    ", 1.0*(maxheap.top() + minheap.top())/2);
                else if(maxheap.size() > minheap.size())
                    printf("%.1f
    ", 1.0*maxheap.top());
                else printf("%.1f
    ", 1.0*minheap.top());
            }
        }
        return 0;
    }
    

      代码没有给注释,简而言之就是,保持两堆元素个数相同&保持堆顶元素大小关系

  • 相关阅读:
    二次开发注意
    LAMP集群项目五 nfs分发文件到服务器
    LAMP集群项目五 nfs存储的数据实时同步到backupserver
    LAMP集群项目五 项目备份
    LAMP集群项目五 部署NFS存储服务并设置WEB服务挂载
    LAMP集群项目四 安装apache、php及其插件
    iOS-单选cell的实现
    iOS-省市区选择的实现
    随机颜色的产生
    刷新轮的使用
  • 原文地址:https://www.cnblogs.com/leafsblogowo/p/13259909.html
Copyright © 2011-2022 走看看