堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 N 个元素,如果 N 是偶数,则中值定义为第 N/2 小元;若是奇数,则为第 (N+1)/2 小元。
输入格式:
输入的第一行是正整数 N(≤105)。随后 N 行,每行给出一句指令,为以下 3 种之一:
Push key Pop PeekMedian
其中
key
是不超过 105 的正整数;Push
表示“入栈”;Pop
表示“出栈”;PeekMedian
表示“取中值”。输出格式:
对每个
Push
操作,将key
插入堆栈,无需输出;对每个Pop
或PeekMedian
操作,在一行中输出相应的返回值。若操作非法,则对应输出Invalid
。输入样例:
17 Pop PeekMedian Push 3 PeekMedian Push 2 PeekMedian Push 1 PeekMedian Pop Pop Push 5 Push 4 PeekMedian Pop Pop Pop Pop
输出样例:
Invalid Invalid 3 2 2 1 2 4 4 5 3 Invalid
题意:模拟栈的输入输出,还要求知道栈排序后第n/2个元素;
思路:
可以使用两个set(l , r)来维护排序;
将三个要求分装为三个函数;
l的最后一个元素<= r的第一个元素,并且l的大小要求>=r的大小,这样每次取出第n/2大的元素就是l的最后一个元素;
pop函数:
如果栈空了就输出错误,否则弹出第一个元素并记录,在set(l,r)中找到这个元素并删除;
void pop(){
if(!st.size()){
cout << "Invalid\n";
return;
}
int x = st.top();
st.pop();
if(l.find(x)!=l.end()){
l.erase(l.find(x));
}else r.erase(r.find(x));
cout << x << endl;
}
push函数:
输入一个数,放入栈和 l 中;
void push(){
int num;cin >> num;
l.insert(num);
st.push(num);
}
peek函数:
栈空输出错误,否则输出l的最后一个值;
void peek(){
if(!st.size()){
cout << "Invalid\n";
return;
}
auto i = l.end();
i --;
cout << *i << endl;
}
l_r函数:
为了维护两个set的合法性;
如果l的尾部元素大于r,就放入r,并从l中删除
当l的大小 <r的大小,就把r的首元素放入l并删除
当l的大小>r的大小+1,就把l的尾部元素放入r并删除;
void l_r(){
while(l.size() && r.size()){
auto i = l.end();
auto j = r.begin();
i --;
if(* i > * j){
r.insert(* i);
l.erase(i);
}else break;
}
while(l.size() < r.size()){
auto i = r.begin();
l.insert(*i);
r.erase(i);
}
while(l.size() > r.size() + 1){
auto i = l.end();
i --;
r.insert(*i);
l.erase(i);
}
}
总代码:
#include<bits/stdc++.h>
using namespace std;
multiset<int>l,r;
stack<int>st;
void l_r(){
while(l.size() && r.size()){
auto i = l.end();
auto j = r.begin();
i --;
if(* i > * j){
r.insert(* i);
l.erase(i);
}else break;
}
while(l.size() < r.size()){
auto i = r.begin();
l.insert(*i);
r.erase(i);
}
while(l.size() > r.size() + 1){
auto i = l.end();
i --;
r.insert(*i);
l.erase(i);
}
}
void pop(){
if(!st.size()){
cout << "Invalid\n";
return;
}
int x = st.top();
st.pop();
if(l.find(x)!=l.end()){
l.erase(l.find(x));
}else r.erase(r.find(x));
cout << x << endl;
}
void push(){
int num;cin >> num;
l.insert(num);
st.push(num);
}
void peek(){
if(!st.size()){
cout << "Invalid\n";
return;
}
auto i = l.end();
i --;
cout << *i << endl;
}
int main(){
int T;cin >> T;
while(T --){
string s;
cin >> s;
if(s == "Pop")pop();
if(s == "Push")push();
if(s == "PeekMedian")peek();
l_r();
}
}