Swap
Enfoque 1
Complejidad: tiempo con de memoria.
Sean los elementos de nodos de un grafo y cada intercambio potencial una arista entre dos nodos. Notamos que este grafo es un árbol binario. Efectivamente queremos realizar algunos intercambios para minimizar el orden BFS de este árbol.
Sea el árbol con como raíz y y como los subárboles de los hijos izquierdo y derecho de respectivamente. Podemos calcular en tiempo .
Ahora podemos formular un estado básico de DP. Sea la versión del subárbol del nodo tras algunos intercambios tales que inicialmente y el orden BFS de es mínimo. Sean y los hijos izquierdo y derecho del nodo respectivamente. Vale la siguiente recurrencia:
La respuesta al problema es entonces . Si calculamos esta DP de forma naive, obtenemos una solución que usa de memoria (ya que ).
Para mejorar esta solución, notamos que para algún , tenemos solo si es hijo de un ancestro de . Como solo hay ancestros de y cada uno tiene a lo sumo 2 hijos, ¡esto nos permite recortar la complejidad temporal (y de memoria) a ! Por conveniencia, seguimos refiriéndonos al estado original de DP en el resto de esta solución.
Sin embargo, esta DP sigue usando demasiada memoria. Hay que hacer dos cosas para arreglarlo:
- Procesar el árbol en orden BFS inverso (es decir, partiendo del nodo y trabajando de vuelta al nodo 1). Esto nos permite liberar la memoria usada por y después de procesar algún nodo . Esto recorta la memoria usada a , pero sigue siendo un poco de más.
- Solo calcular los estados de los que depende . Por ejemplo, el valor de es irrelevante si .
Estas dos optimizaciones nos ahorran justo la memoria suficiente para obtener AC.
Implementación
#include <bits/stdc++.h>
using namespace std;
int a[200002];
bool needed[200002][18][2];
vector<int> dp[200002][18][2], tmp1, tmp2;
void merge(vector<int> &ret, vector<int> &l, vector<int> &r) {
for (int i = 0, j = 1; i < l.size(); i += j, j <<= 1) {
for (int k = i; k < i + j && k < l.size(); k++) ret.push_back(l[k]);
for (int k = i; k < i + j && k < r.size(); k++) ret.push_back(r[k]);
}
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", a + i);
needed[1][0][1] = 1;
for (int node = 1; node <= n / 2; node++) {
for (int i = 0; node >> i; i++)
for (int j : {0, 1}) {
if (!needed[node][i][j]) continue;
int mn =
min({a[((node >> i + 1) << 1) + j], a[2 * node], a[2 * node + 1]});
if (mn == a[((node >> i + 1) << 1) + j]) {
needed[2 * node][0][0] = needed[2 * node + 1][0][1] = 1;
} else if (mn == a[2 * node]) {
needed[2 * node][i + 1][j] = needed[2 * node + 1][0][1] = 1;
} else {
needed[2 * node][0][0] = needed[2 * node][i + 1][j] = 1;
needed[2 * node + 1][0][0] = needed[2 * node + 1][i + 1][j] = 1;
}
}
}
for (int node = n; node; node--) {
for (int i = 0; node >> i; i++)
for (int j : {0, 1}) {
if (!needed[node][i][j]) continue;
int p = ((node >> i + 1) << 1) + j;
if (2 * node > n) dp[node][i][j] = {a[p]};
else if (2 * node == n) {
dp[node][i][j] = {min(a[p], a[2 * node]), max(a[p], a[2 * node])};
} else {
if (a[2 * node + 1] < min(a[p], a[2 * node])) {
tmp1 = tmp2 = {a[2 * node + 1]};
merge(tmp1, dp[2 * node][0][0], dp[2 * node + 1][i + 1][j]);
merge(tmp2, dp[2 * node][i + 1][j], dp[2 * node + 1][0][0]);
dp[node][i][j] = min(tmp1, tmp2);
} else {
dp[node][i][j] = {min(a[p], a[2 * node])};
if (a[p] < a[2 * node]) {
merge(dp[node][i][j], dp[2 * node][0][0],
dp[2 * node + 1][0][1]);
} else {
merge(dp[node][i][j], dp[2 * node][i + 1][j],
dp[2 * node + 1][0][1]);
}
}
}
}
if (2 * node < n) {
for (int i = 0; 2 * node >> i; i++)
for (int j : {0, 1}) {
vector<int>().swap(dp[2 * node][i][j]);
vector<int>().swap(dp[2 * node + 1][i][j]);
}
}
}
for (int i : dp[1][0][1]) printf("%d ", i);
return 0;
}Enfoque 2
Algo de DP mágica. Ver la discusión en CF .
Implementación
Complejidad temporal: , se puede reducir a .
Complejidad de memoria:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using db = double;
using str = string; // yay python!
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vd = vector<db>;
using vs = vector<str>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vpd = vector<pd>;
#define tcT template <class T
#define tcTU tcT, class U
// ^ lol this makes everything look weird but I'll try it
tcT > using V = vector<T>;
tcT, size_t SZ > using AR = array<T, SZ>;
tcT > using PR = pair<T, T>;
// pairs
#define mp make_pair
#define f first
#define s second
// vectors
// oops size(x), rbegin(x), rend(x) need C++17
#define sz(x) int((x).size())
#define bg(x) begin(x)
#define all(x) bg(x), end(x)
#define rall(x) x.rbegin(), x.rend()
#define sor(x) sort(all(x))
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pb push_back
#define eb emplace_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
tcT > int lwb(V<T> &a, const T &b) { return int(lb(all(a), b) - bg(a)); }
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b) - 1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define trav(a, x) for (auto &a : x)
const int MOD = 1e9 + 7; // 998244353;
const int MX = 2e5 + 5;
const ll INF = 1e18; // not too close to LLONG_MAX
const ld PI = acos((ld)-1);
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; // for every grid problem!!
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
// bitwise ops
// also see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
constexpr int bits(int x) { // assert(x >= 0); // make C++11 compatible until
// USACO updates ...
return x == 0 ? 0 : 31 - __builtin_clz(x);
} // floor(log2(x))
constexpr int p2(int x) { return 1 << x; }
constexpr int msk2(int x) { return p2(x) - 1; }
ll cdiv(ll a, ll b) {
return a / b + ((a ^ b) > 0 && a % b);
} // divide a by b rounded up
ll fdiv(ll a, ll b) {
return a / b - ((a ^ b) < 0 && a % b);
} // divide a by b rounded down
tcT > bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } // set a = min(a,b)
tcT > bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
tcTU > T fstTrue(T lo, T hi, U f) {
hi++;
assert(lo <= hi); // assuming f is increasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo) / 2;
f(mid) ? hi = mid : lo = mid + 1;
}
return lo;
}
tcTU > T lstTrue(T lo, T hi, U f) {
lo--;
assert(lo <= hi); // assuming f is decreasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo + 1) / 2;
f(mid) ? lo = mid : hi = mid - 1;
}
return lo;
}
tcT > void remDup(vector<T> &v) { // sort and remove duplicates
sort(all(v));
v.erase(unique(all(v)), end(v));
}
tcTU > void erase(T &t, const U &u) { // don't erase
auto it = t.find(u);
assert(it != end(t));
t.erase(it);
} // element that doesn't exist from (multi)set
// INPUT
#define tcTUU tcT, class... U
tcT > void re(complex<T> &c);
tcTU > void re(pair<T, U> &p);
tcT > void re(V<T> &v);
tcT, size_t SZ > void re(AR<T, SZ> &a);
tcT > void re(T &x) { cin >> x; }
void re(db &d) {
str t;
re(t);
d = stod(t);
}
void re(ld &d) {
str t;
re(t);
d = stold(t);
}
tcTUU > void re(T &t, U &...u) {
re(t);
re(u...);
}
tcT > void re(complex<T> &c) {
T a, b;
re(a, b);
c = {a, b};
}
tcTU > void re(pair<T, U> &p) { re(p.f, p.s); }
tcT > void re(V<T> &x) { trav(a, x) re(a); }
tcT, size_t SZ > void re(AR<T, SZ> &x) { trav(a, x) re(a); }
tcT > void rv(int n, V<T> &x) {
x.rsz(n);
re(x);
}
// TO_STRING
#define ts to_string
str ts(char c) { return str(1, c); }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
str ts(bool b) {
#ifdef LOCAL
return b ? "true" : "false";
#else
return ts((int)b);
#endif
}
tcT > str ts(complex<T> c) {
stringstream ss;
ss << c;
return ss.str();
}
str ts(V<bool> v) {
str res = "{";
F0R(i, sz(v)) res += char('0' + v[i]);
res += "}";
return res;
}
template <size_t SZ> str ts(bitset<SZ> b) {
str res = "";
F0R(i, SZ) res += char('0' + b[i]);
return res;
}
tcTU > str ts(pair<T, U> p);
tcT > str ts(T v) { // containers with begin(), end()
#ifdef LOCAL
bool fst = 1;
str res = "{";
for (const auto &x : v) {
if (!fst) res += ", ";
fst = 0;
res += ts(x);
}
res += "}";
return res;
#else
bool fst = 1;
str res = "";
for (const auto &x : v) {
if (!fst) res += " ";
fst = 0;
res += ts(x);
}
return res;
#endif
}
tcTU > str ts(pair<T, U> p) {
#ifdef LOCAL
return "(" + ts(p.f) + ", " + ts(p.s) + ")";
#else
return ts(p.f) + " " + ts(p.s);
#endif
}
// OUTPUT
tcT > void pr(T x) { cout << ts(x); }
tcTUU > void pr(const T &t, const U &...u) {
pr(t);
pr(u...);
}
void ps() { pr("\n"); } // print w/ spaces
tcTUU > void ps(const T &t, const U &...u) {
pr(t);
if (sizeof...(u)) pr(" ");
ps(u...);
}
// DEBUG
void DBG() { cerr << "]" << endl; }
tcTUU > void DBG(const T &t, const U &...u) {
cerr << ts(t);
if (sizeof...(u)) cerr << ", ";
DBG(u...);
}
#ifdef LOCAL // compile with -DLOCAL, chk -> fake assert
#define dbg(...) \
cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define chk(...) \
if (!(__VA_ARGS__)) \
cerr << "Line(" << __LINE__ << ") -> function(" << __FUNCTION__ \
<< ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", \
exit(0);
#else
#define dbg(...) 0
#define chk(...) 0
#endif
void setPrec() { cout << fixed << setprecision(15); }
void unsyncIO() { cin.tie(0)->sync_with_stdio(0); }
// FILE I/O
void setIn(str s) { freopen(s.c_str(), "r", stdin); }
void setOut(str s) { freopen(s.c_str(), "w", stdout); }
void setIO(str s = "") {
unsyncIO();
setPrec();
// cin.exceptions(cin.failbit);
// throws exception when do smth illegal
// ex. try to read letter into int
if (sz(s)) setIn(s + ".in"), setOut(s + ".out"); // for USACO
}
map<pi, int> bes;
int n, p[MX];
int get(int ind, int y) {
if (bes.count({ind, y})) return bes[{ind, y}];
if (2 * ind > n) return ind;
if (2 * ind + 1 > n) {
if (y > p[2 * ind]) return 2 * ind;
return ind;
}
if (y < min(p[2 * ind], p[2 * ind + 1])) return bes[{ind, y}] = ind;
if (p[2 * ind] < min(y, p[2 * ind + 1])) return bes[{ind, y}] = get(2 * ind, y);
int mn = min(y, p[2 * ind]);
if (get(2 * ind, mn) < get(2 * ind + 1, mn)) {
if (mn == y) return bes[{ind, y}] = get(2 * ind, y);
return bes[{ind, y}] = get(2 * ind + 1, y);
} else {
if (mn == y) return bes[{ind, y}] = get(2 * ind + 1, y);
return bes[{ind, y}] = get(2 * ind, y);
}
}
void solve(int ind) {
if (2 * ind > n) return;
if (2 * ind + 1 > n) {
if (p[ind] > p[2 * ind]) swap(p[ind], p[2 * ind]);
return;
}
if (p[ind] < min(p[2 * ind], p[2 * ind + 1])) {
} else if (p[2 * ind] < min(p[ind], p[2 * ind + 1])) {
swap(p[2 * ind], p[ind]);
} else {
int mn = min(p[ind], p[2 * ind]), mx = max(p[ind], p[2 * ind]);
p[ind] = p[2 * ind + 1];
if (get(2 * ind, mn) < get(2 * ind + 1, mn)) {
p[2 * ind] = mn, p[2 * ind + 1] = mx;
} else {
p[2 * ind] = mx, p[2 * ind + 1] = mn;
}
}
solve(ind + 1);
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n;
FOR(i, 1, n + 1) cin >> p[i];
solve(1);
FOR(i, 1, n + 1) cout << p[i] << " ";
}Enfoque 3
Mantenemos alguna colección de heaps y calculamos la secuencia en orden. Creo que esto es similar a lo que hace la solución oficial, aunque no lo entiendo del todo.
Implementación
Complejidad temporal:
Complejidad de memoria:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using db = double;
using str = string; // yay python!
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vd = vector<db>;
using vs = vector<str>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vpd = vector<pd>;
#define tcT template <class T
#define tcTU tcT, class U
// ^ lol this makes everything look weird but I'll try it
tcT > using V = vector<T>;
tcT, size_t SZ > using AR = array<T, SZ>;
tcT > using PR = pair<T, T>;
// pairs
#define mp make_pair
#define f first
#define s second
// vectors
// oops size(x), rbegin(x), rend(x) need C++17
#define sz(x) int((x).size())
#define bg(x) begin(x)
#define all(x) bg(x), end(x)
#define rall(x) x.rbegin(), x.rend()
#define sor(x) sort(all(x))
#define rsz resize
#define ins insert
#define ft front()
#define bk back()
#define pb push_back
#define eb emplace_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
tcT > int lwb(V<T> &a, const T &b) { return int(lb(all(a), b) - bg(a)); }
// loops
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i, 0, a)
#define ROF(i, a, b) for (int i = (b) - 1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define trav(a, x) for (auto &a : x)
const int MOD = 1e9 + 7; // 998244353;
const int MX = 2e5 + 5;
const ll INF = 1e18; // not too close to LLONG_MAX
const ld PI = acos((ld)-1);
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}; // for every grid problem!!
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
// bitwise ops
// also see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
constexpr int bits(int x) { // assert(x >= 0); // make C++11 compatible until
// USACO updates ...
return x == 0 ? 0 : 31 - __builtin_clz(x);
} // floor(log2(x))
constexpr int p2(int x) { return 1 << x; }
constexpr int msk2(int x) { return p2(x) - 1; }
ll cdiv(ll a, ll b) {
return a / b + ((a ^ b) > 0 && a % b);
} // divide a by b rounded up
ll fdiv(ll a, ll b) {
return a / b - ((a ^ b) < 0 && a % b);
} // divide a by b rounded down
tcT > bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } // set a = min(a,b)
tcT > bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
tcTU > T fstTrue(T lo, T hi, U f) {
hi++;
assert(lo <= hi); // assuming f is increasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo) / 2;
f(mid) ? hi = mid : lo = mid + 1;
}
return lo;
}
tcTU > T lstTrue(T lo, T hi, U f) {
lo--;
assert(lo <= hi); // assuming f is decreasing
while (lo < hi) { // find first index such that f is true
T mid = lo + (hi - lo + 1) / 2;
f(mid) ? lo = mid : hi = mid - 1;
}
return lo;
}
tcT > void remDup(vector<T> &v) { // sort and remove duplicates
sort(all(v));
v.erase(unique(all(v)), end(v));
}
tcTU > void erase(T &t, const U &u) { // don't erase
auto it = t.find(u);
assert(it != end(t));
t.erase(it);
} // element that doesn't exist from (multi)set
// INPUT
#define tcTUU tcT, class... U
tcT > void re(complex<T> &c);
tcTU > void re(pair<T, U> &p);
tcT > void re(V<T> &v);
tcT, size_t SZ > void re(AR<T, SZ> &a);
tcT > void re(T &x) { cin >> x; }
void re(db &d) {
str t;
re(t);
d = stod(t);
}
void re(ld &d) {
str t;
re(t);
d = stold(t);
}
tcTUU > void re(T &t, U &...u) {
re(t);
re(u...);
}
tcT > void re(complex<T> &c) {
T a, b;
re(a, b);
c = {a, b};
}
tcTU > void re(pair<T, U> &p) { re(p.f, p.s); }
tcT > void re(V<T> &x) { trav(a, x) re(a); }
tcT, size_t SZ > void re(AR<T, SZ> &x) { trav(a, x) re(a); }
tcT > void rv(int n, V<T> &x) {
x.rsz(n);
re(x);
}
// TO_STRING
#define ts to_string
str ts(char c) { return str(1, c); }
str ts(const char *s) { return (str)s; }
str ts(str s) { return s; }
str ts(bool b) {
#ifdef LOCAL
return b ? "true" : "false";
#else
return ts((int)b);
#endif
}
tcT > str ts(complex<T> c) {
stringstream ss;
ss << c;
return ss.str();
}
str ts(V<bool> v) {
str res = "{";
F0R(i, sz(v)) res += char('0' + v[i]);
res += "}";
return res;
}
template <size_t SZ> str ts(bitset<SZ> b) {
str res = "";
F0R(i, SZ) res += char('0' + b[i]);
return res;
}
tcTU > str ts(pair<T, U> p);
tcT > str ts(T v) { // containers with begin(), end()
#ifdef LOCAL
bool fst = 1;
str res = "{";
for (const auto &x : v) {
if (!fst) res += ", ";
fst = 0;
res += ts(x);
}
res += "}";
return res;
#else
bool fst = 1;
str res = "";
for (const auto &x : v) {
if (!fst) res += " ";
fst = 0;
res += ts(x);
}
return res;
#endif
}
tcTU > str ts(pair<T, U> p) {
#ifdef LOCAL
return "(" + ts(p.f) + ", " + ts(p.s) + ")";
#else
return ts(p.f) + " " + ts(p.s);
#endif
}
// OUTPUT
tcT > void pr(T x) { cout << ts(x); }
tcTUU > void pr(const T &t, const U &...u) {
pr(t);
pr(u...);
}
void ps() { pr("\n"); } // print w/ spaces
tcTUU > void ps(const T &t, const U &...u) {
pr(t);
if (sizeof...(u)) pr(" ");
ps(u...);
}
// DEBUG
void DBG() { cerr << "]" << endl; }
tcTUU > void DBG(const T &t, const U &...u) {
cerr << ts(t);
if (sizeof...(u)) cerr << ", ";
DBG(u...);
}
#ifdef LOCAL // compile with -DLOCAL, chk -> fake assert
#define dbg(...) \
cerr << "Line(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define chk(...) \
if (!(__VA_ARGS__)) \
cerr << "Line(" << __LINE__ << ") -> function(" << __FUNCTION__ \
<< ") -> CHK FAILED: (" << #__VA_ARGS__ << ")" << "\n", \
exit(0);
#else
#define dbg(...) 0
#define chk(...) 0
#endif
void setPrec() { cout << fixed << setprecision(15); }
void unsyncIO() { cin.tie(0)->sync_with_stdio(0); }
// FILE I/O
void setIn(str s) { freopen(s.c_str(), "r", stdin); }
void setOut(str s) { freopen(s.c_str(), "w", stdout); }
void setIO(str s = "") {
unsyncIO();
setPrec();
// cin.exceptions(cin.failbit);
// throws exception when do smth illegal
// ex. try to read letter into int
if (sz(s)) setIn(s + ".in"), setOut(s + ".out"); // for USACO
}
int n, p[MX];
int par[MX];
vi val[MX], child[MX];
int qmin(int x) {
if (!par[x]) {
assert(p[x]);
return p[x];
}
assert(p[x] == 0);
x = par[x];
int res = MOD;
while (x) {
assert(sz(val[x]));
trav(t, val[x]) ckmin(res, t);
if (sz(val[x]) == 2) {
assert(!par[x]);
break;
} else {
assert(sz(val[x]) == 1 && par[x]);
x = par[x];
}
}
assert(res != MOD);
return res;
}
void delChild(int a, int b) {
assert(a && par[b] == a);
auto it = find(all(child[a]), b);
assert(it != end(child[a]));
child[a].erase(it);
par[b] = 0;
}
void setChild(int a, int b) {
assert(a);
child[a].pb(b);
par[b] = a; // assert(p[b]);
p[b] = 0;
}
void setEq(int x) {
if (p[x]) return;
int v = qmin(x);
vi trail = {x};
while (find(all(val[trail.bk]), v) == end(val[trail.bk])) {
assert(trail.bk);
trail.pb(par[trail.bk]);
}
for (; sz(trail) > 1; trail.pop_back()) {
int t = trail.bk;
assert(sz(val[t]) && sz(child[t]) == 2);
int c = trail[sz(trail) - 2], C = child[t][0] + child[t][1] - c;
val[c].pb(v);
delChild(t, c);
delChild(t, C);
if (sz(val[t]) == 2) {
val[C].pb(val[t][0] + val[t][1] - v);
} else {
int P = par[t];
delChild(P, t);
setChild(P, C);
}
}
}
int main() {
setIO();
re(n);
FOR(i, 1, n + 1) re(p[i]);
FOR(i, 1, n + 1) {
if (!par[i] && sz(val[i])) {
assert(sz(val[i]) == 1 && p[i] == 0);
p[i] = val[i][0];
val[i] = {};
}
int x = qmin(i);
int mn = x;
if (2 * i <= n) ckmin(mn, p[2 * i]);
if (2 * i + 1 <= n) ckmin(mn, p[2 * i + 1]);
if (mn == x) setEq(i); // just remove the min
else if (mn == p[2 * i]) { // don't touch p[2*i+1]
if (!par[i]) p[2 * i] = p[i];
else {
int P = par[i];
delChild(P, i);
setChild(P, 2 * i);
}
} else {
if (!par[i]) val[i] = {p[i], p[2 * i]};
else val[i] = {p[2 * i]};
setChild(i, 2 * i), setChild(i, 2 * i + 1);
}
pr(mn, ' ');
}
// you should actually read the stuff at the bottom
}