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;
}
posted @ 2020-04-27 17:44  South1999  阅读(165)  评论(0编辑  收藏  举报