堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 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
题解
要求的是中值的小元,就是要把输入按从小到大排序,然后取中间那个值
关键点:利用lower_bound(begin,end,num)
函数,每次遇到一个数时,找到该数对应的插入位置。lower_bound 是找到第一个大于等于 num 的位置
这样就能永远保证 vector 是有序的
比如原来 vector 中是 3 5
现在要插入 4
用 lower_bound 找到的位置就是 5 ,将 4 插入 5 这个位置,原来 5 则往后顺移一位
#include <bits/stdc++.h>
using namespace std;
ostream &sp(ostream &output);
int a[100000];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("read.txt", "r", stdin);
freopen("write.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(false);
vector<int> ans;
int n;
cin >> n;
int cnt = 0;
string opreration;
while (n--)
{
cin >> opreration;
if (opreration == "Push")
{
int num;
cin >> num;
a[cnt++] = num;
auto it = lower_bound(ans.begin(), ans.end(), a[cnt - 1]);
ans.insert(it, num);
cout<<"ans = ";
for(auto it:ans)
cout<<it<<sp;
cout<<endl;
}
else if (opreration == "Pop")
{
if (cnt <= 0)
cout << "Invalid" << endl;
else
{
auto it = lower_bound(ans.begin(), ans.end(), a[cnt - 1]);
ans.erase(it);
cout << a[cnt - 1] << endl;
cnt -= 1;
}
}
else if (opreration == "PeekMedian")
{
if (ans.empty())
cout << "Invalid" << endl;
else
{
int loc;
if (ans.size() % 2 == 0)
loc = ans.size() / 2;
else
loc = (ans.size() + 1) / 2;
cout << ans[loc - 1] << endl;
}
}
}
return 0;
}
ostream &sp(ostream &output)
{
return output << " ";
}