pat 1057. Stack (30)
Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<= 105). Then N lines follow, each contains a command in one of the following 3 formats:
Push keyPop
PeekMedian
where key is a positive integer no more than 105.
Output Specification:
For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print "Invalid" instead.
Sample Input:17 Pop PeekMedian Push 3 PeekMedian Push 2 PeekMedian Push 1 PeekMedian Pop Pop Push 5 Push 4 PeekMedian Pop Pop Pop PopSample Output:
Invalid Invalid 3 2 2 1 2 4 4 5 3 Invalid
//18:45
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
#define MAX 120000
//树状数组大家看解释可以明白,是在log(n)的复杂度之内,对数组进行区域求和,修改某个值。
//看之前,大家要明白,树状数组的含义。即是,数组上的没一个数字,其含义并不是一数字,而是管辖着某一范围的数组
//他是他所管辖区域所有数组的和,这个被管辖的实际数组并不存在,只存在概念当中,当然,也可以用真是的数组表示
//这个数字所管辖的范围是 sn = a[n+1-2^k]...a[n].k代表n的二进制末尾零的个数。
//树状数组三个很重要的函数是 lowbit(),sum,update();
//每一个函数的意思是 lowbit(x) = x&(-x).lowbit(x)就是求x的2^k. x+lowbit(x)就到了管辖他的父节点。
//x-lowbit(x)就到了他所在区域的下一个区域。sum(x)求x之前,实际数组所有数字的和,实际数组也是那个概念当中的数组
//update(x)表示修改实际数组的某一个数字,但是其所有父节点都需要更改
//而本题树状数组,利用的是统计的特性。数组上的每一个数字代表该以该索引为值的数字出现过的次数,初始时没有数字
//所以全部都是零,每插入一个数字,那么以这个数字为索引的值便加一。没删除一个数字,该索引上的值便减一。
//由于树状数组的特性,管辖这个数字的所有父节点.也都要+1,这样就可以保证数字是有序的。
//对于查找中位数,利用的并非纯粹的二分查找。只有当当前值大于现在所求的和,才进行向右查找。小于或者等于的情况,都是
//向左查找。最后找到一个临界值,把l输出便是结果。
struct Tree
{
vector<int> tree;
Tree()
{
tree = vector<int>(MAX,0);
}
//求2^k,k为x的末位连续0的个数
int lowerBit(int x)
{
return x&(-x);
}
//更新实际某个数组的值,在这道题当中。1代表num增加多了一个,然后其父节点都得统计+1
//-1代表num少了一个,然后其父节点都得统计-1;
void update(int num,int val)
{
while(num<MAX)
{
tree[num] += val;
num += lowerBit(num);
}
return ;
}
//统计num之前总共有多少个数字,而中位数就是get(num)==n/2的那个,
int getSum(int num)
{
int sum = 0;
while(num>0)
{
sum += tree[num];
num -= lowerBit(num);
}
return sum;
}
//二分查找,在index大于sum的情况下,向右移动。index小于或者等于sum,都向左移动。
//最后根据二分查找的原理,能够找到恰好和是index的那个索引
int find(int index)
{
int l = 1,h=MAX-1,tmp=0,mid;
while(l<=h)
{
mid = (l+h)/2;
tmp = getSum(mid);
// can only judge the minimal one
if(tmp<index)
{
l = mid+1;
}else
{
h = mid-1;
}
}
return l;
}
};
Tree t;
int main()
{
int n,tmp;
int i,j;
char ope[13];
vector<int> sta;
//freopen("pat1057engTest.txt","r",stdin);
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",ope);
if(strcmp(ope,"Pop")==0)
{
if(sta.size()==0)
{
printf("Invalid\n");
}else
{
tmp = sta.back();
sta.pop_back();
t.update(tmp,-1);
printf("%d\n",tmp);
}
}else if(strcmp(ope,"PeekMedian")==0)
{
if(sta.size()==0)
{
printf("Invalid\n");
}else
{
tmp = t.find(1+(sta.size()-1)/2);
printf("%d\n",tmp);
}
}else if(strcmp(ope,"Push")==0)
{
scanf("%d",&tmp);
sta.push_back(tmp);
t.update(tmp,1);
}else
{
printf("Invalid\n");
}
}
return 0;
}