数据结构水题大赛官方题解#3 XXX的stl

数据结构水题大赛 T3

XXX的stl

题面

洛谷链接

题解

本题要求查询一个数组最大值, 插入一个数字, 随机删除一个元素. 有(20')的暴力得分, (20')的priority_queue得分, 正解是手打大根堆

20'暴力

这个不用说了, 直接几层循环套娃就能过

20'stl

往priority_queue里插入元素, 查询时直接返回q.top

100'手写大根堆

大根堆很好处理, 查询是直接返回根节点, 但是由于删除是按照下标 (插入顺序) 检索的, 所以在存入大根堆的同时还要捆绑一个下标.

由于知道了下标不一定知道在大根堆里的位置, 所以还要维护一个数组Num[]通过下标定位到大根堆中的位置.

由于随机删除会减少大根堆元素数量, 但是下标不会减少, 所以需要两个cnt变量, 一个存实际的元素数量, 用于维护插入元素的位置, 另一个存累计元素数量, 来为新元素分配下标.

AC代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;
int t, n, m, a[400005], ans = 0, cnt = 0, cnt1 = 0, Dui[400005][2], Do, Num[400005];
bool flg;
char ch;
string s;
inline int IN() {
	char ich = getchar();
	int intmp = 0, insign = 1;
	while (((ich < '0') || (ich > '9')) && ((ich != '-'))) {
		ich = getchar();
	}
	if (ich == '-') {
		insign = -1;
		ich = getchar();
	}
	while ((ich <= '9') && (ich >= '0')) {
		intmp *= 10;
		intmp += ich - '0';
		ich = getchar();
	}
	return intmp * insign;
}
void Add (int x) {
	cnt++;
	cnt1++;
	Num[cnt] = cnt;
	Dui[cnt][0] = x;
	Dui[cnt][1] = cnt1;
	int now = cnt;
	while (Dui[now][0] > Dui[now >> 1][0]) {
		swap(Dui[now][0], Dui[now >> 1][0]);
		swap(Dui[now][1], Dui[now >> 1][1]);
		Num[Dui[now][1]] = now;
		Num[Dui[now >> 1][1]] = now >> 1;
		now = now >> 1;
	}
	return;
}
void Del(int x) {
	if(Num[x] == 0) {
		return;
	}
	int now = Num[x];
	Num[x] = 0; 
	Dui[now][0] = Dui[cnt][0];
	Dui[now][1] = Dui[cnt][1];
	cnt--;
	while (Dui[now][0] < max(Dui[now << 1][0], Dui[(now << 1) + 1][0])) {
		if(Dui[now << 1][0] <= Dui[(now << 1) + 1][0]){
			swap(Dui[now][0], Dui[(now << 1) + 1][0]);
			swap(Dui[now][1], Dui[(now << 1) + 1][1]);
			Num[Dui[now][1]] = now;
			Num[Dui[(now << 1) + 1][1]] = (now << 1) + 1;
			now = (now << 1) + 1;
		}
		else {
			swap(Dui[now][0], Dui[now << 1][0]);
			swap(Dui[now][1], Dui[now << 1][1]);
			Num[Dui[now][1]] = now;
			Num[Dui[now << 1][1]] = now << 1;
			now = now << 1;
		}
	}
	while (Dui[now][0] > Dui[now >> 1][0]) {
		swap(Dui[now][0], Dui[now >> 1][0]);
		swap(Dui[now][1], Dui[now >> 1][1]);
		Num[Dui[now][1]] = now;
		Num[Dui[now >> 1][1]] = now >> 1;
		now = now >> 1;
	}
	return;
}
int main() {
	n = IN();
	memset(Dui, 0, sizeof(Dui));
	Dui[0][0] = 0x3f3f3f3f;
	for (register int i = 1; i <= n; i++) {
		Add(IN());
	}
	m = IN();
	for (register int i = 1; i <= m; i++) {
		Do = IN();
		switch (Do) {
			case 0 : {
				if(cnt == 0){
					printf("%d
",-0x3f3f3f3f); 
				}
				else{ 
					printf("%d
", Dui[1][0]);
				}
				break;
			}
			case 1 : {
				Add(IN());
				break;
			}
			case 2 : {
				Del(IN());
				break;
			}
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Wild-Donkey/p/13329965.html