P4785 [BalticOI 2016 Day2]交换
pitiless0514 · · 题解
Statement
一个长度为
要求最小化字典序,
Solution
题目的操作很有特性,看到
考虑当前在点
那么注意到按照操作顺序,
于是大力分类讨论。
当
当
接下来观察子节点
一定不可能,因为交换
当
不失一般性假设
所以我们可以在写一个爆搜,同样按照我们上面的三条策略,搜出
然后爆搜写的是
记得在爆搜中第三种情况的时候讨论一下
复杂度的话,注意到假如访问到一个点
代码用 map 实现的,总复杂度就为
// 德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱德丽莎你好可爱
// 德丽莎的可爱在于德丽莎很可爱,德丽莎为什么很可爱呢,这是因为德丽莎很可爱!
// 没有力量的理想是戏言,没有理想的力量是空虚
#include <bits/stdc++.h>
#define LL long long
using namespace std;
char ibuf[1 << 15], *p1, *p2;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, 1 << 15, stdin), p1==p2) ? EOF : *p1++)
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x * f;
}
void print(LL x) {
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> bool chkmin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool chkmax(T &a, T b) { return a < b ? (a = b, true) : false; }
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define repd(i, l, r) for (int i = (l); i >= (r); i--)
#define REP(i, l, r) for (int i = (l); i < (r); i++)
const int N = 2e6;
int n, p[N];
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
map < pair<int,int>,int> mp;
int find(int u,int v,int id) {
if (u > n) return id;
if (mp.find({u, v}) != mp.end()) return mp[{u, v}];
int &b = p[ls(u)], &c = p[rs(u)], &w = mp[{u, v}];
if (v < min(b, c)) return w = u;
if (b < c) return w = find(ls(u), v, u);
else if (b < v) {
int lans = find(ls(u), b, u);
int rans = find(rs(u), b, u);
if (lans > rans) {
return w = find(ls(u), v, u);
} else {
return w = find(rs(u), v, u);
}
} else {
return w = min(find(u << 1, v, u), find(u << 1 | 1, v, u));
}
}
void work(int u) {
if (u > n) return;
int &a = p[u], &b = p[ls(u)], &c = p[rs(u)];
if (a < min(b, c)) {
work(ls(u));
work(rs(u));
return;
}
if (b < c) {
swap(a, b);
work(ls(u));
work(rs(u));
return;
}
swap(a, c);
if (b > c) swap(b, c);
if (find(ls(u), b, ls(u)) > find(rs(u), b, rs(u))) swap(b, c);
work(ls(u));
work(rs(u));
}
void solve() {
n = read();
rep (i, 1, n) p[i] = read();
rep (i, n + 1, 2 * n + 1) p[i] = n + 1;
work(1);
rep (i, 1, n) cout << p[i] << " ";
}
signed main () {
#ifdef LOCAL_DEFINE
freopen("1.in", "r", stdin);
freopen("1.ans", "w", stdout);
#endif
int T = 1; while (T--) solve();
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}