栈是最基本的数据结构之一,它基于后进先出(LIFO)的原理。
基本操作包括“入栈”(将元素插入到顶部位置)和“出栈”(删除顶部元素)。
现在,你需要实现一个栈,该栈要具有一个额外的操作:PeekMedian-返回栈中所有元素的中值。
对于 N 个元素,如果 N 为偶数,则中值定义从小到大第 N/2 个元素;如果 N 为奇数,则中值定义为从小到大第 N+1/2个元素。
输入格式
第一行包含整数 N,表示命令数。
接下来 N 行,每行包含以下三种命令中的一种:
Push key
Pop
PeekMedian
其中 key 是一个不超过 10的5次方 的正整数。
输出格式
对于每个 Push 操作,在顶部插入一个 key 值,不输出任何内容。
对于每个 Pop 或 PeekMedian 命令,在一行中输出相应的返回值。
如果命令无效,则输出 Invalid。
数据范围
1≤N≤105
输入样例:
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
直接暴力会超时,用树状数组
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int tr[N];
stack<int> s;
int lowbit(int i){
return i&(-i);
}
void add(int x,int v){
for(int i=x;i<N;i+=lowbit(i))tr[i]+=v;
}
int getsum(int x){
int res=0;
for(int i=x;i;i-=lowbit(i))res+=tr[i];
return res;
}
void Peekmedian(){ //有单调性可以用二分
int left=1,right=N,mid,k=(s.size()+1)/2;
while(left<right){
mid=left+right>>1;
if(getsum(mid)>=k)right=mid;
else left=mid+1;
}
cout<<left<<endl;
}
int main(){
int n;
char str[20];
cin>>n;
while(n--){
scanf("%s",str);
if(strcmp(str,"Push")==0){
int x;
scanf("%d",&x);
s.push(x);
add(x,1);
}
else if(strcmp(str,"Pop")==0){
if(s.empty()){
cout<<"Invalid"<<endl;
}
else{
cout<<s.top()<<endl;
add(s.top(),-1);
s.pop();
}
}
else if(strcmp(str,"PeekMedian")==0){
if(s.empty()){
cout<<"Invalid"<<endl;
}
else{
Peekmedian();
}
}
}
return 0;
}