UESTC 1063 秋实大哥与妹纸 二叉堆(大根树)

秋实大哥与妹纸

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 1500/1500KB (Java/Others)
Submit  Status

致中和,天地位焉,万物育焉。秋实大哥是一个追求中庸的人。

虽然秋实大哥的仰慕者众多,但秋实大哥不喜欢极端的妹纸。所以他想从所有仰慕自己的妹纸中挑选出一个符合中庸之道的。

每一个妹纸对秋实大哥的仰慕程度可以用一个整数 ai 来表示,秋实大哥想要找出这些数的中位数。

计算有限个数的数据的中位数的方法是:

把所有的同类数据按照大小的顺序排列。如果数据的个数是奇数,则中间那个数据就是这群数据的中位数;
如果数据的个数是偶数,则中间那2个数据的算术平均值就是这群数据的中位数。

Input

第一行有一个整数 n ,表示秋实大哥的仰慕者数目。

接下来 n 行,每行有一个正整数 ai

1n250000 1ai<231

Output

输出这 n 个数的中位数,保留一位小数。

Sample input and output

Sample Input Sample Output
3
1
2
3
2.0

Hint

注意内存大小限制。

Source

2015 UESTC Training for Data Structures
The question is from here.

My Solution

 Memory Limit: 1500/1500KB (Java/Others)
卡内存的题目,第一次遇到 (┬_┬)
维护好n/2+1个元素就好,后面的push,然后pop
本来用C++STL的priority_queue写了一个,结果爆内存了,MLE
所以用二叉堆来写

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 125001;

int heap[maxn],  sz = 1;

void up(int i) {
    int x = heap[i];

    for(int j = i/2; j >= 1; j/=2) {            //前面这里打成了 i ,结果WA2 而不是WA1, 估计是test2的一些数据触发bug吧☺
        if(heap[j] > x){
            heap[i] = heap[j];
            i = j;
        } else {
            break;
        }
    }
    heap[i] = x;
}
void down(int i) {
    int x = heap[i];

    for(int j = i*2; j <= sz; j*=2){
        j += j < sz&& heap[j] > heap[j+1];
        if(heap[j] < x){
            heap[i] = heap[j];
            i = j;
        } else {
            break;
        }
    }
    heap[i] = x;
}
void push(int v) {
    heap[++sz] = v;
    up(sz);
}
void pop() {
    swap(heap[1], heap[sz]);
    sz--;
    down(1);
}
int top() {
    return heap[1];
}

int main()
{
    int n, a;
    scanf("%d", &n);
    for(int i = 0; i < n/2 +1; i++){
        scanf("%d", &a);push(a);
    }
    for(int i = n/2 +1; i < n; i++){
        scanf("%d", &a);
        push(a);pop();
    }
    pop();
    if(n % 2 ==1) printf("%.1f", (double)heap[1]);
    else{
        a = top();pop();
        printf("%.1f", (double)a/2+(double)top()/2);
    }
    return 0;
}

thank you!

你可能感兴趣的:(数据结构,ACM,二叉堆,大根树,卡内存)