-可并堆-并查集- [洛谷 P1456]Monkey King

题目描述

Link

Solution

这道题比较麻烦的操作就是修改操作,我主要讲一下修改操作。

我是这么做的:

如果这个堆的大小是1,那么直接修改。

如果不是,则将最大权值的节点删除,新建一个节点,权值为被删除节点的权值的一半,再与之前的节点合并。

最后将两个堆合并就行了。

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 2000010
struct Heap {
int v, id;
int s, xd;
}h[MAXN];
int fa[MAXN], a[MAXN], siz[MAXN];
bool ifd[MAXN];
int merge(int a, int b) {
if (h[a].v == 0) return b;
if (h[b].v == 0) return a;
if (h[a].v < h[b].v || (h[a].v == h[b].v && a < b)) std::swap(a, b);
h[b].xd = h[a].s;
h[a].s = b;
return a;
}
int merges(int a) {
if (h[a].v == 0 || h[h[a].xd].v == 0) return a;
int p = h[a].xd, q = h[p].xd;
h[a].xd = h[p].xd = 0;
return merge(merge(a, p), merges(q));
}
int del(int a) {
h[a].v = -1;
return merges(h[a].s);
}
int find(int x) {
if (fa[x] == x) return x;
else return fa[x] = find(fa[x]);
}
bool un(int x, int y) {
fa[y] = x;
return 1;
}
int head[MAXN], x, y, n, m, cnt;
void push(int a, int &p) {
cnt++;
head[cnt] = cnt;
h[cnt].v = a;
h[cnt].id = cnt;
h[cnt].s = h[cnt].xd = 0;
fa[cnt] = cnt;
siz[cnt] = 1;
p = merge(cnt, p);
}
char op[5];
int main() {
while (scanf("%d", &n) != EOF) {
// scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
fa[i] = i;
}
h[0].v = 0;
cnt = 0;
for (int i = 1; i <= n; i++) {
head[i] = i;
h[i].v = a[i];
h[i].id = i;
h[i].s = h[i].xd = 0;
siz[i] = 1;
}
cnt = n;
scanf("%d", &m);
while (m--) {
scanf("%d%d", &x, &y);
int _x = find(x), _y = find(y);
if (_x == _y) {
puts("-1");
continue;
}
bool fl1 = 0, fl2 = 0;
if (siz[head[_x]] == 1) {
h[head[_x]].v /= 2;
fl1 = 1;
}
if (siz[head[_y]] == 1) {
h[head[_y]].v /= 2;
fl2 = 1;
}
if (!fl1) {
int f = h[head[_x]].v;
head[_x] = del(head[_x]);
push(f / 2, head[_x]);
}
if (!fl2) {
int g = h[head[_y]].v;
head[_y] = del(head[_y]);
push(g / 2, head[_y]);
}
un(_x, _y);
head[_x] = merge(head[_x], head[_y]);
siz[head[_x]] += siz[head[_y]];
printf("%d\n", h[head[_x]].v);
}
}
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2019/11/07/110/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论