[PAT-A 1057]Stack

在这里插入图片描述
在这里插入图片描述
题目大意:
给出一个栈的入栈出栈过程,并随时通过PeekMedian命令要求输出栈中中位数,Pop命令输出出栈的数。
当栈中没有元素时,Pop命令和PeekMedian命令都应该输出"Invalid"。

思路:
1)关于实时查询数组元素中第k大的元素。
所谓实时查询就是在查询过程中会有元素不断的添加与删除,如果每次都排序会超时,因此考虑如下策略:

1.考虑将N个元素分为sqrt(N)块,其中每块sqrt(N)个元素。则除最后一块,每一块都应该有sqrt(N)个元素。
2.元素序列中都是不超过10^5的非负整数,设置hashTable[100010],其中hashTable[x]表示整数x的存在个数。
3.定义整型数组block[317],其中block[i]表示第i块中存在的元素个数,加入要新增一个元素,则令block[x/316]加一,表示该块中元素多了1,同时令table[x]+1,表示整数x的当前个数+1。
4.查询第K大的数,从小到大枚举块号,利用block数组累加前i-1块元素总个数,判断加入i号块之后元素的总个数能否达到k,如果可以,说明第k大的数就在当前枚举的这个块中,此时只需要从小到大遍历该块中的每个元素,利用hashTable数组
累加元素存在的个数,直到总数累计到达k,则说明找见了第K大的数。

2)根据入栈出栈指令,对栈进行操作,push入栈,pop指令输出栈顶元素,同时对hashTable与block数组进行操作,PeekMedian输出当前栈中中间的元素,即k取中间位置进行查询。

AC代码:

//PAT_A 1040
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 100010;
const int sqrN = 316;//分块个数
stack<int> st;
int block[sqrN], table[maxn];
void PeekMedian(int k) {
	int sum = 0, index = 0;//当前累计存在的个数,块号
	while (sum + block[index] < k) {
		sum += block[index];
		index++;
	}
	int num = index * sqrN;
	while (sum + table[num] < k) {
		sum += table[num];
		num++;
	}
	printf("%d\n", num);
	return;
}
void push(int x) {
	st.push(x);
	block[x / sqrN]++;
	table[x]++;
}
void pop() {
	int x = st.top();
	st.pop();
	block[x / sqrN]--;
	table[x]--;
	printf("%d\n", x);
}
int main() {
	int x, query;
	char cmd[20];
	fill(block, block + sqrN, 0);
	fill(table, table + maxn, 0);
	(void)scanf("%d", &query);
	for (int i = 0; i < query; i++) {
		(void)scanf("%s", cmd);
		if (strcmp(cmd, "Push") == 0) {
			(void)scanf("%d", &x);
			push(x);
		}
		else if (strcmp(cmd, "Pop") == 0) {
			if (st.empty() == true)printf("Invalid\n");
			else pop();
		}
		else {
			if (st.empty() == true)printf("Invalid\n");
			else {
				int k = st.size();
				if (k % 2 == 1)k = k / 2 + 1;
				else k /= 2;
				PeekMedian(k);
			}
		}
	}
	return 0;
}
发布了157 篇原创文章 · 获赞 1 · 访问量 6063

猜你喜欢

转载自blog.csdn.net/weixin_44699689/article/details/104727244