题目大意:给定一个栈的操作序列,push,pop,peekmedian,其中peekmedian为获取栈的中值
方法一:巧用mutilset,stack维护普通的查询,multiset维护前半段与后半段,则中值为前段的末尾值。
(写了这题后才恍然大悟,multiset这不就是加强版的优先队列嘛,既可以获取最大值最小值,还可以进行遍历。这也太方便了,只不过可能时间复杂度有点高)
(注意,multiset没有.back()函数,只能先获取.end(),然后进行--操作获取尾元素)
#include<bits/stdc++.h>
using namespace std;
stack<int>stk;
multiset<int>l,r;
void keep(){
while(r.size()>l.size()){
l.insert(*r.begin());
r.erase(r.begin());
}
while(l.size()>r.size()+1){
auto it=l.end();it--;
r.insert(*it);
l.erase(it);
}
}
int main(){
int m;cin>>m;
while(m--){
string op;cin>>op;
if(op=="Push"){
int a;cin>>a;
if(r.empty()||*r.begin()>a)l.insert(a);
else r.insert(a);
stk.push(a);
keep();
}
else if(op=="Pop"){
if(stk.size()){
int t=stk.top();
cout<<stk.top()<<endl;
stk.pop();
if(l.size()&&l.find(t)!=l.end()){
l.erase(l.find(t));
}
else r.erase(r.find(t));
keep();
}
else cout<<"Invalid"<<endl;
}else {
if(!stk.size()){
cout<<"Invalid"<<endl;continue;
}
auto x=l.end();x--;
cout<<*x<<endl;
}
}
}
方法二:树状数组,维护每个数的出现次数,再二分查找中间数字即可。