PAT 甲级 1057 Stack(树状数组解法)
本题有一定的难度,如果用普通的栈和数组搭配去做会超时,后来去网上查了做法,有人说可以用树状数组做。本题大致意思就是给定一个栈,有三种操作,分别是push数入栈、pop出栈和寻找栈中按顺序排列的最中间的数,我们可以用一个树状数组记录每个数字存在的次数,配合二分法,每次去求1到n的和,也就是1到n出现了多少次,直到两个边界相遇,趁着本题也算复习了一下树状数组。树状数组------树状数组详解
#include <iostream>
#include <string>
#include <stack>
using namespace std;
const int maxn=100000;
int c[maxn+5];
int update(int i,int k)
{
while(i<=maxn)
{
c[i]+=k;
i+=i&(-i);
}
}
int getsum(int i)
{
int res=0;
while(i>0)
{
res+=c[i];
i-=i&(-i);
}
return res;
}
stack<int> st;
int main()
{
int cnt=0,tmp;
int n;
cin>>n;
string op;
for(int i=0;i<n;i++)
{
cin>>op;
if(op=="Pop")
{
if(cnt==0)
{
cout<<"Invalid\n";
}
else
{
tmp=st.top();
st.pop();
update(tmp,-1);
cnt--;
cout<<tmp<<endl;
}
}
else if(op=="Push")
{
int u;
cin>>u;
st.push(u);
update(u,1);
cnt++;
}
else if(op=="PeekMedian")
{
if(cnt==0)
{
cout<<"Invalid\n";
continue;
}
int l=1,r=maxn,mid,goal;
if(cnt%2==0) goal=cnt/2;
else goal=(cnt+1)/2;
while(l<=r)
{
mid=(l+r)/2;
if(getsum(mid)>=goal)
{
r=mid-1;
}
else
{
l=mid+1;
}
}
cout<<l<<endl;
}
}
return 0;
}