zoukankan      html  css  js  c++  java
  • P3871 [TJOI2010]中位数

    题目描述

    给定一个由N个元素组成的整数序列,现在有两种操作:

    1 add a

    在该序列的最后添加一个整数a,组成长度为N + 1的整数序列

    2 mid 输出当前序列的中位数

    中位数是指将一个序列按照从小到大排序后处在中间位置的数。(若序列长度为偶数,则指处在中间位置的两个数中较小的那个)

    例1:1 2 13 14 15 16 中位数为13

    例2:1 3 5 7 10 11 17 中位数为7

    例3:1 1 1 2 3 中位数为1

    输入输出格式

    输入格式:

    第一行为初始序列长度N。第二行为N个整数,表示整数序列,数字之间用空格分隔。第三行为操作数M,即要进行M次操作。下面为M行,每行输入格式如题意所述。

    输出格式:

    对于每个mid操作输出中位数的值

    输入输出样例

    输入样例#1: 
    6
    1 2 13 14 15 16
    5
    add 5
    add 3
    mid
    add 20
    mid
    
    输出样例#1: 
    5
    13
    

    说明

    对于30%的数据,1 ≤ N ≤ 10,000,0 ≤ M ≤ 1,000

    对于100%的数据,1 ≤ N ≤ 100,000,0 ≤ M ≤ 10,000

    序列中整数的绝对值不超过1,000,000,000,序列中的数可能有重复

     

    Solution:

    本题有很多做法。

    1、先说一种简单点的,使用“对顶堆”的在线算法。为了动态维护中位数,我们可以建立两个二叉堆,一个小根堆一个大根堆,在读入序列时,注意:将从小到大排名为1~n/2的整数放在大根堆中,将从小到大排名为n/2+1~n的整数放在小根堆中。

    每次新读入一个数x后,若x比大根堆顶小,则放入大根堆,否则放入小根堆。在查询时,若某个大根堆元素个数过多(>n/2),则将多余的元素放入小根堆,那么若此时n为奇数则中位数为小根堆堆顶,否则就是大根堆堆顶,直接输出就OK了。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define debug printf("%d%s
    ",__LINE__,__FUNCTION__)
    using namespace std;
    const int N=100005;
    il int gi()
    {
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    priority_queue<int,vector<int>,greater<int> >qmin;
    priority_queue<int>qmax;
    int n,x,mid,a[N],m,cn1,cn2;
    int main()
    {
        n=gi();m=n;
        for(int i=1;i<=n;i++)a[i]=gi();
        sort(a+1,a+n+1);
        for(int i=1;i<=n/2;i++)qmax.push(a[i]),cn1++;
        for(int i=n/2+1;i<=n;i++)qmin.push(a[i]),cn2++;
        n=gi();char s[10];
        while(n--){
            scanf("%s",s);
            if(s[0]=='a'){
                scanf("%d",&x);
                if(x<qmax.top())qmax.push(x),cn1++;
                else qmin.push(x),cn2++;
                m++;
            }
            else {
                while(cn1<m/2){
                    x=qmin.top();qmin.pop();qmax.push(x);cn1++;cn2--;
                }
                while(cn1>m/2){
                    x=qmax.top();qmax.pop();qmin.push(x);cn2++;cn1--;
                }
                if(m&1)printf("%d
    ",qmin.top());
                else printf("%d
    ",qmax.top());
            }
        }
        return 0;
    }

    2、“链表+hash”离线做法(留坑)。

    3、还有一种无脑的平衡树在线做法(留坑,自我感觉大才小用了)。

  • 相关阅读:
    Luckysheet如何初始化含合并单元格的数据
    Luckysheet如何一键导入本地Excel
    又发现一款纯js开源电子表格Luckysheet
    Sublime Text3 注册码(Windows/Build 3176版本)| 开发工具
    Python初学者笔记(4)-简单的通讯录
    Python初学者笔记(3):输出列表中的奇数/奇数项,字符串中的偶数项,字符串大小写转换
    安装wampserver出现“The Program can't start because MSVCR110.dll is missing from your computer. Try reinstalling the program to fix this problem”
    python初学者笔记(2):阿拉伯数字转换成中文大写
    Python初学者笔记:打印出斐波那契数列的前10项
    JavaScript弹出对话框的三种方式
  • 原文地址:https://www.cnblogs.com/five20/p/8509376.html
Copyright © 2011-2022 走看看