题解
第一种方法:令数组tree[]记录栈中的元素,栈中的数值 x 的个数为 tree[x] 。树状数组维护tree[],然后二分查找。
第二种方法:利用分块,以一定长度区间为单位,记录栈中数值的个数,然后暴力查找。
代码
//树状数组 + 二分
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
int tree[maxn];
stack<int> sta;
void update(int p,int w);
int sum(int p);
int main()
{
int n,w,left,right,mid,k;
string op;
scanf("%d",&n);
while(n--)
{
cin>>op;
if(op[1]=='u')
{
scanf("%d",&w);
sta.push(w);
update(w,1);
}
else
{
if(sta.size()<1) printf("Invalid
");
else if(op[1]=='o')
{
printf("%d
",sta.top());
update(sta.top(),-1);
sta.pop();
}
else
{
left=0;right=maxn;k=(sta.size()+1)/2;
while(left<=right)
{
mid=(left+right)/2;
if(sum(mid)>=k) right=mid-1;
else left=mid+1;
}
printf("%d
",left);
}
}
}
system("pause");
return 0;
}
void update(int p,int w)
{
for(;p<maxn;p += p&(-p))
tree[p]+=w;
}
int sum(int p)
{
int ans=0;
for(;p>0;p -= p&(-p))
ans+=tree[p];
return ans;
}
//分块
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010,block_size=367;
int cnt[maxn],block[280];
stack<int> sta;
void PUSH_POP(int index,int v);
int Find(int k);
int main()
{
int n,w;
string op;
scanf("%d",&n);
while(n--)
{
cin>>op;
if(op[1]=='u')
{
scanf("%d",&w);
sta.push(w);
PUSH_POP(w,1);
}
else
{
if(sta.size()<1) printf("Invalid
");
else if(op[1]=='o')
{
printf("%d
",sta.top());
PUSH_POP(sta.top(),-1);
sta.pop();
}
else printf("%d
",Find((sta.size()+1)/2));
}
}
system("pause");
return 0;
}
void PUSH_POP(int index,int v)
{
cnt[index]+=v;
block[index/block_size]+=v;
}
int Find(int k)
{
int sum=0,i=0,index;
while(sum + block[i] < k)
sum+=block[i++];
index=block_size*i;
while(1)
{
if(sum + cnt[index] >= k) return index;
else sum+=cnt[index],index++;
}
}