L3-002 堆栈 树状数组+二分答案

题目详情点击这里

思路:用std::stack来表示题目中说的栈,现在关键问题就是如何找到中位数。

可以用二分答案+树状数组的方法

由于每个元素最大不超过1e5,因此开一个大小为1e5的树状数组来存储不超过x的数有多少个

每次push一个元素,都把以它为下标的树状数组位置+1,pop就相当于-1

这样的话sum(x)的含义就是栈中不超过x的数有多少个。然后就可以用二分的方法把答案确定出来了。

因为中位数x肯定要满足sum(x) >= N/2 或者sum(x) >= (N+1)/2

以前太菜了,现在看这道题目,感觉不难

代码:

#include 
#include 
#include 
using namespace std;
const int MAX = 1e5;
stack stk;
int bitree[MAX + 10];
int N;
inline int lowbit(int x)
{
	return x&(-x);
}
void add(int pos,int x)
{
	while(pos <= MAX)
	{
		bitree[pos] += x;
		pos += lowbit(pos);
	}
}
int sum(int pos)
{
	int res = 0;
	while(pos > 0)
	{
		res += bitree[pos];
		pos -= lowbit(pos);
	}
	return res;
}
bool check(int x,int size)
{
	if(N&2 == 0)
		return sum(x) >= size/2; 
	else return sum(x) >= (size+1)/2;
}
int main()
{
	scanf("%d",&N);
	char ops[20];
	for(int i = 0;i < N;i++){
		scanf("%s",ops);
		if(ops[1] == 'o')
		{
			if(stk.empty())
				puts("Invalid");
			else{
				int val = stk.top();stk.pop();
				add(val,-1);
				printf("%d\n",val);
			}
		}
		else if(ops[1] == 'u')
		{
			int val;scanf("%d",&val);
			stk.push(val);
			add(val,1);
		}
		else
		{
			if(stk.empty()){puts("Invalid");continue;}
			
			int l = 0,r = MAX;
			while(l < r)
			{
				int m = (l+r)/2;
				if(check(m,stk.size()))
					r = m;
				else
					l = m+1;
			}
			printf("%d\n",l);
		}
	}
	return 0;
 } 



你可能感兴趣的:(ACM-ICPC训练题解)