P3871 [TJOI2010]中位数

Posted five20

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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了。

代码:

 1 #include<bits/stdc++.h>
 2 #define il inline
 3 #define ll long long
 4 #define debug printf("%d%s\n",__LINE__,__FUNCTION__)
 5 using namespace std;
 6 const int N=100005;
 7 il int gi()
 8 {
 9     int a=0;char x=getchar();bool f=0;
10     while((x<0||x>9)&&x!=-)x=getchar();
11     if(x==-)x=getchar(),f=1;
12     while(x>=0&&x<=9)a=a*10+x-48,x=getchar();
13     return f?-a:a;
14 }
15 priority_queue<int,vector<int>,greater<int> >qmin;
16 priority_queue<int>qmax;
17 int n,x,mid,a[N],m,cn1,cn2;
18 int main()
19 {
20     n=gi();m=n;
21     for(int i=1;i<=n;i++)a[i]=gi();
22     sort(a+1,a+n+1);
23     for(int i=1;i<=n/2;i++)qmax.push(a[i]),cn1++;
24     for(int i=n/2+1;i<=n;i++)qmin.push(a[i]),cn2++;
25     n=gi();char s[10];
26     while(n--){
27         scanf("%s",s);
28         if(s[0]==a){
29             scanf("%d",&x);
30             if(x<qmax.top())qmax.push(x),cn1++;
31             else qmin.push(x),cn2++;
32             m++;
33         }
34         else {
35             while(cn1<m/2){
36                 x=qmin.top();qmin.pop();qmax.push(x);cn1++;cn2--;
37             }
38             while(cn1>m/2){
39                 x=qmax.top();qmax.pop();qmin.push(x);cn2++;cn1--;
40             }
41             if(m&1)printf("%d\n",qmin.top());
42             else printf("%d\n",qmax.top());
43         }
44     }
45     return 0;
46 }

 

2、“链表+hash”离线做法。

 

 

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

以上是关于P3871 [TJOI2010]中位数的主要内容,如果未能解决你的问题,请参考以下文章

TJOI2010中位数

[TJOI2010]中位数

省选刷题记录

P3879 [TJOI2010]阅读理解(Trie)

LGOJ3879 TJOI2010 阅读理解

「字典树」[TJOI2010]阅读理解