数据结构水题大赛 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;
}