这题其他的好做,关键是查询中间值,用个树状数组维护值的数量,然后用二分查找在中间的值就好。
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <math.h>
#include <time.h>
#include <map>
#define mem(a, b) memset(a, b, sizeof(a))
#define inf (1e8 + 7)
using namespace std;
int st[100005], head = 0, num[100005], num2[100005];
bool vis[100005];
char ch[25];
void add(int a)
{
for(int i = a;i <= 100000;i += (i&(-i)))
num[i]++;
}
void sub(int a)
{
for(int i = a;i <= 100000;i += (i&(-i)))
num[i]--;
}
int get(int a)
{
int sum = 0;
for(int i = a;i > 0;i -= (i&(-i)))
sum += num[i];
return sum;
}
int solve(int a)
{
int lo = 1, hi = 100000;
while(lo <= hi)
{
int mid = (lo + hi) / 2;
int tmp1 = get(mid - 1);
int tmp2 = get(mid);
if(tmp1 < a&&tmp2 >= a)
{
if(num2[mid])
return mid;
for(int i = mid - 1;i >= 1;i--)
if(num2[i])
return i;
}
else if(tmp1 >= a)
hi = mid - 1;
else
lo = mid + 1;
}
}
void push(int a)
{
st[++head] = a;
num2[a]++;
add(a);
}
void pop()
{
if(!head)
printf("Invalid\n");
else
{
int tmp = st[head--];
num2[tmp]--;
sub(tmp);
printf("%d\n", tmp);
}
}
void getmid()
{
if(!head)
printf("Invalid\n");
else
{
int pos;
if(head % 2)
pos = (head + 1) / 2;
else
pos = head / 2;
printf("%d\n", solve(pos));
}
}
int main ()
{
mem(num, 0);
mem(num2, 0);
int n, a;
scanf("%d", &n);
for(int i = 1;i <= n;i++)
{
scanf("%s", ch);
if(!strcmp(ch, "Pop"))
pop();
else if(!strcmp(ch, "PeekMedian"))
getmid();
else if(!strcmp(ch, "Push"))
{
scanf("%d", &a);
push(a);
}
else
printf("Invalid\n");
}
return 0;
}