题目内容
浦島太郎被海龟带到龙宫,过了三年吃香喝辣的舒适生活后,准备回家乡探(炫)亲(耀)。临走时,小龙女送给他一个漆黑的木箱子,说里面装有各种奇珍异宝。回到原先居住的渔村后,浦島太郎叫来全村的老少,吹嘘龙宫的宝贝如何如何好,要让大家开开眼界。但当他正准备打开箱子时,箱子中突然传出声音:”想要打开箱子的话必须先回答问题。问题很简单!我连续报N个数出来,每报一个数,你马上跟着说一个数,并且是我之前报的所有数值中的最大、最小和中位数的平均值。如果你回答错了或者回答慢了,箱子就会立刻消失。”浦島太郎被吓得直冒冷汗,但夸下的海口又不好意思收回,只好硬着头皮接受挑战。请你帮他完成任务。
注:把包含n(>0)个数值的序列按升序(非递减)排序后,如果n是偶数,则排在2/n和2/n+1位的两个数是中位数;如果n是奇数,排在2/n+1位的是中位数。
输入格式
输入在第一行中给出整数N (1≤N≤4×10^5)。接下来一行给出N个非负整数,数值间用空格隔开,末尾的数值后面没有空格。所有数值不超过10^8。
输出格式
在一行中输出N个整数,第i个数值(1≤i≤N)表示输入的前i个整数中的最大值、最小值及中位数的平均值(整除)。数值间用空格分开,末尾的数值后面没有空格。
输入样例
5
3 2 1 4 5
输出样例
3 2 2 2 3
题目样例分析
{3},平均值: (3+3+3)/3 = 3
{3,2},平均值: (2+2+3+3)/4=2
{3,2,1},平均值: (1+2+3)/3=2
{3,2,1,4},平均值: (1+2+3+4)/4=2
{3,2,1,4,5},平均值: (1+3+5)/3=3
限制
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
思路分析
由于题目数据规模大,使用平常的数组存储后排序,或者是每次进行插入排序都会导致时间超过限制。现提供如下思路:
最大值与最小值的求法:
直接使用max和min存储,每次输入即进行比较,比较后更改该值大小。
中位数求法:
建立两个优先级队列,分别是left和right。
left是最大堆,方便取最大元素,堆顶是中位数(轮次为偶数时,为中位数之一),其余元素是小于中位数的元素。
right是最小堆,方便取最小元素,堆顶在偶数轮是中位数之一,其余元素和奇数轮的堆顶是大于中位数的元素。
现每次插入数据,要维护如下规则:
left元素个数等于right元素个数,或,left元素比right元素多一个。
这样就可以很直接求出中位数。
要维护这样的规则,只需要分奇偶轮次,奇数轮保持增加left元素,偶数轮保持增加right元素即可。
具体来说,当想往left插入元素时,需判断是否小于right堆顶元素。如果是,则直接插入,如果不是,则应当插入right中,然后把right堆顶的元素放入left中,才能维护上面的规则。向right中插入同理。
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 1e8 + 10;
const int M = -1e8 - 10;
int n, m, k, T;
signed main() {
cin >> n;
priority_queue<int> left;
priority_queue<int, vector<int>, greater<int>> right;
int max = M;
int min = N;
int lun = 0;
while (n--) {
lun++;
int num, sum;
scanf("%d", &num);
if (num > max) {
max = num;
}
if (num < min) {
min = num;
}
if (left.empty() && right.empty()) {
left.push(num);
} else {
if (left.size() > right.size()) {
if (num >= left.top()) {
right.push(num);
} else {
int temp = left.top();
left.pop();
left.push(num);
right.push(temp);
}
} else {
if (num <= right.top()) {
left.push(num);
} else {
int temp = right.top();
right.pop();
right.push(num);
left.push(temp);
}
}
}
//计算阶段
if (lun != 1) {
printf(" ");
}
if (lun % 2 == 1) {
printf("%d", (min + max + left.top()) / 3);
} else {
printf("%d", (min + max + left.top() + right.top()) / 4);
}
}
printf("\n");
}