1.本题的中间三个测试点非常容易超时
2.需要采用树状数组+二分法
树状数组:能够在o(logn)的时间内进行对a[i]操作和统计a[0]+a[1]+a[2]+...a[i]的操作。
我们把a[i]记录为i的出现次数,那么统计sum=a[0]+a[1]+a[2]+...a[i],就可以知道小于等于i的元素出现的次数。而PeekMedian操作中,是求n/2或者(n+1)/2的元素,即当sum等于n/2或者(n+1)/2时,i就是我们需要输出的元素
3.利用树状数组,能够快速统计sum,利用二分法,能够快速定位i
4.后续优化:可以考虑采用一个数组实现stack的功能,int stack[N]; int stackTop=0;//既是栈顶元素在stack数组的位置,也是栈内元素的总个数,push操作:stack[++stackTop]=x, pop操作:stack[stackTop--].
//#include<string>
//#include<stack>
//#include<unordered_set>
//#include <sstream>
//#include "func.h"
//#include <list>
#include <iomanip>
#include<unordered_map>
#include<set>
#include<queue>
#include<map>
#include<vector>
#include <algorithm>
#include<stdio.h>
#include<iostream>
#include<string>
#include<memory.h>
#include<limits.h>
#include<stack>
using namespace std;
#define MAX_N 100001
int Tree[MAX_N];
inline int lowbit(int x)
{
return(x&-x);
}
void add(int x, int value)
{
for (int i = x; i < MAX_N; i += lowbit(i))
Tree[i] += value;
}
int get(int x)
{//获取0到x的数组总和
int sum = 0;
for (int i = x; i; i -= lowbit(i))
sum += Tree[i];
return sum;
}
int main(void)
{
int n;
cin >> n;
char action[11];
stack<int> sta;
int maxNum = INT_MIN;
int minNum = INT_MAX;
memset(Tree, 0, sizeof(Tree));
for (int i = 0; i < n; i++)
{
scanf("%s", action);
if (action[2] == 'p')
{//pop
if (sta.empty())
{
cout << "Invalid" << endl;
continue;
}
int top = sta.top();
sta.pop();
add(top, -1);//弹出,出现次数减1
printf("%d\n", top);
}
else if (action[2] == 'e')
{//PeekMedian
if (sta.empty())
{
cout << "Invalid" << endl;
continue;
}
int n = sta.size();//栈里的元素个数
int target = 0;
if (n % 2 == 0)
target = n / 2;
else
target = (n + 1) / 2;
//设中位数为i,用二分法查找
int l = 0;
int r = MAX_N - 1;
while (l <r - 1)
{
int mid = (l + r) / 2;
if (get(mid) < target)
l = mid;
else//如果get(mid)<=target,则r=mid,逐渐逼近
r = mid;
}
printf("%d\n", l + 1);
}
else
{//push
int tmp;
scanf("%d", &tmp);
sta.push(tmp);
maxNum = max(maxNum, tmp);
minNum = min(minNum, tmp);
add(tmp, 1);//弹出,出现次数加1
}
}
return 0;
}