-
Notifications
You must be signed in to change notification settings - Fork 11
/
SPOJ11772.cc
126 lines (117 loc) · 3 KB
/
SPOJ11772.cc
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// SPOJ 11772: Negative Score
// http://www.spoj.com/problems/RPLN/
//
// Solution: offline range minimum query (cartesian tree)
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <functional>
using namespace std;
#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
template <class T>
struct cartesian_tree {
int n, root;
vector<T> x;
vector<int> l, r, p;
cartesian_tree(const vector<T> &x)
: n(x.size()), x(x), l(n,-1), r(n,-1), p(n,-1) {
root = 0;
for (int i = 1; i < n; ++i) {
int j = i-1;
while (p[j] >=0 && x[i] < x[j]) j = p[j];
if (x[i] < x[j]) {
p[j] = i;
l[i] = j;
root = i;
} else {
if (r[j] >= 0) p[r[j]] = i;
l[i] = r[j];
p[i] = j;
r[j] = i;
}
}
}
// In-order traverse gives an original sequence
void traverse(int t, int tab = 0) {
if (t < 0) return;
traverse(l[t], tab + 2);
for (int i = 0; i < tab; ++i) cout << " ";
cout << x[t] << endl;
traverse(r[t], tab + 2);
}
void traverse() {
traverse(root);
}
// Sorting in O(n log k) by Levcopoulos-Petersson
void sort() {
auto comp = [&](int i, int j) { return x[i] > x[j]; };
priority_queue<int, vector<int>, decltype(comp)> que(comp);
que.push(root);
while (!que.empty()) {
int t = que.top(); que.pop();
cout << x[t] << " ";
if (l[t] >= 0) que.push(l[t]);
if (r[t] >= 0) que.push(r[t]);
}
cout << endl;
}
struct union_find {
vector<int> p;
union_find(int n) : p(n, -1) { };
bool unite(int u, int v) {
if ((u = root(u)) == (v = root(v))) return false;
if (p[u] > p[v]) swap(u, v);
p[u] += p[v]; p[v] = u;
return true;
}
int root(int u) { return p[u] < 0 ? u : p[u] = root(p[u]); }
};
struct query { int u, v, a; };
void range_min_queries(vector<query> &queries) {
vector<vector<query*>> Q(n);
for (auto &q: queries) {
Q[q.u].push_back(&q);
Q[q.v].push_back(&q);
}
union_find uf(n);
vector<int> anc(n), color(n);
iota(all(anc), 0);
function<void (int)> rec = [&](int u) {
for (int c: {l[u], r[u]}) {
if (c < 0) continue;
rec(c);
uf.unite(c, u);
anc[uf.root(u)] = u;
}
color[u] = 1;
for (auto it: Q[u]) {
if (it->u != u) swap(it->u, it->v);
if (color[it->v] == 1) it->a = anc[uf.root(it->v)];
}
};
rec(root);
}
};
int main() {
int ncase; scanf("%d", &ncase);
for (int icase = 0; icase < ncase; ++icase) {
printf("Scenario #%d:\n", icase+1);
int n, q; scanf("%d %d", &n, &q);
vector<int> x(n);
for (int i = 0; i < n; ++i)
scanf("%d", &x[i]);
cartesian_tree<int> T(x);
vector<cartesian_tree<int>::query> qs(q);
for (int i = 0; i < q; ++i) {
scanf("%d %d", &qs[i].u, &qs[i].v);
--qs[i].u; --qs[i].v;
}
T.range_min_queries(qs);
for (auto q: qs)
printf("%d\n", x[q.a]);
}
}