1057 Stack(树状数组+二分)
用树状数组求插入栈中的数据的中位数(第k小的数):
将插入的数据作为树状数组的下标就可以自动完成排序,更新对应结点的数值,表示该结点覆盖的区间内的节点数,通过比较从开始到该节点区间内的数据个数和中位数的位置的大小关系可以找到中位数。
#include <iostream>
#include <string.h>
#include<stack>
#include<algorithm>
using namespace std;
#define lowbit(x) ((x)&(-x))//表示x结点所覆盖的范围
//c[x]包含了从A[x]开始往左的lowbit(x)个结点的和
const int MAXSIZE = 100010;
int N;
int c[MAXSIZE];
stack<int> s;
void update(int x, int v)
{//维护树状数组
for (int i = x; i < MAXSIZE; i += lowbit(i))
c[i] += v;
}
int get_sum(int x)
{//计算[0,x]区间内的结点个数
int sum = 0;
for (int i = x; i >=1; i -= lowbit(i))
sum += c[i];
return sum;
}
int peekmadian(int k)
{
int left = 1, right = MAXSIZE;
int mid;
while (left < right)
{
mid = (left + right) / 2;
if (get_sum(mid) < k)
left = mid + 1;//左边的数少
else
right = mid;//左边的数多
}
return left;
}
int main()
{
memset(c, 0, sizeof(c));
cin >> N;
char commend[15];
for (int i = 0; i < N; i++)
{
scanf("%s", commend);
if (commend[1] == 'o')
{
if (s.size() != 0)
{
printf("%d\n", s.top());
update(s.top(), -1);
s.pop();
}
else
printf("Invalid\n");
}
else
if (commend[1] == 'u')
{
int num = 0;
scanf("%d", &num);
update(num, 1);
s.push(num);
}
else
if (s.size() != 0)
printf("%d\n", peekmadian((s.size()+1)/2));
else
printf("Invalid\n");
}
return 0;
}