Description
题目大意:在Stack的原有功能上增加了PeekMedian功能,即排好序后求中位数
Input
Push key
Pop
PeekMedian
Output
相应操作的值
解题思路
算法标签:树状数组
首先分析为什么用树状数组。显然对于pop和push两种操作无需考虑,在求中位数时候,为了得到中位数,显然需要排序好的序列才能得到,如果每次都得排序,显然时间复杂度会很高,如果是快排的话(O(nlgn)),最坏情况可能为(O(n2lgn))。所以关键问题在于查询。假设tree[n]记录0-N区间内节点个数,这样查找中位数的时候,只需要找到左右两边节点个数相同的那个值即为中位数,而tree[n]本来就是1-N有序的,所以自然不需要排序
代码
// TSWorld
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int N = 100005;
int stack[N];
int tree[N];
inline int lowbit(int x)
{
return x&(-x);
}
void Change(int index,int delta)
{
while(index <= N)
{
tree[index] += delta;
index += lowbit(index);
}
}
int Query(int index)
{
int sum = 0;
while(index > 0)
{
sum += tree[index];
index -= lowbit(index);
}
return sum;
}
int find(int value)
{
int l = 0,r = N;
int mid = 0,tot = 0;
while(l < r-1)
{
mid = (l+r)/2;
tot = Query(mid);
if(tot < value)
l = mid;
else
r = mid;
}
return l+1;
}
int main()
{
string command;
int n = 0,key = 0;
int top = 0,ans = 0;
cin>>n;
for(int i = 1;i <= n;i++)
{
cin>>command;
if(command == "Push")
{
cin>>key;
stack[++top] = key;
Change(key,1);
}
else if(command == "Pop")
{
if(top > 0){
cout<<stack[top]<<endl;
Change(stack[top],-1);
top--;
}
else
cout<<"Invalid\n";
}
else
{
if(top == 0){
cout<<"Invalid\n";
continue;
}
if(top%2 == 0)
ans = find(top/2);
else
ans = find((top+1)/2);
cout<<ans<<endl;
}
}
return 0;
}