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
由于要O(1)输出栈的中位数,想到利用set的自动排序,将栈中的元素都哈希到set。如果题目条件保证栈中元素不重复,只用一个set辅助即可,set最中间的元素即为中位数。由于栈中元素可能重复,所以用两个multiset进行辅助,set1存储小于等于当前中位数mid的,set2存储大于mid的,set1中最大的数即为mid。set1的大小必须与set2相等(栈的大小为偶数),或多1(栈的大小为奇数),这是平衡态。每次栈push或者pop后,调整两个set平衡,重新计算mid。
/*2015.7.27cyq*/ #include <iostream> #include <vector> #include <set> #include <stack> #include <cstring> using namespace std; stack<int> stk; multiset<int> set1,set2; int mid; //set1存mid及以下的数,其大小应该与set2相等,或多1 void adjust(){ if(set1.size()<set2.size()){//将set2最小的移到set1 auto it=set2.begin(); set1.insert(*it); set2.erase(it); }else if(set1.size()>set2.size()+1){//将set1最大的移到set2 auto it=set1.end(); it--; set2.insert(*it); set1.erase(it); } //重新计算mid if(!stk.empty()){ auto it=set1.end(); it--; mid=*it; } } int main(){ int N; scanf("%d",&N); char ch[12]; int top,x; while(N--){ scanf("%s",ch); if(strcmp(ch,"Pop")==0){ if(stk.empty()) printf("Invalid\n"); else{ top=stk.top(); stk.pop(); printf("%d\n",top); if(top<=mid) set1.erase(set1.find(top)); else set2.erase(set2.find(top)); adjust(); } }else if(strcmp(ch,"PeekMedian")==0){ if(stk.empty()) printf("Invalid\n"); else printf("%d\n",mid); }else if(strcmp(ch,"Push")==0){ scanf("%d",&x); stk.push(x); if(stk.empty()){ set1.insert(x); mid=x; }else if(x<=mid) set1.insert(x); else set2.insert(x); adjust(); }else printf("Invalid\n"); } return 0; }