# Luogu4402 机械排序

## Description

$i$次操作时，找到区间$[1, n]$中第$i$小的数的位置$p_i$，并翻转区间$[i, p_i]$

## Solution

$p_i​$序列就边操作边输出就可以了

## Code

#include <bits/stdc++.h>

using namespace std;

#define fst first
#define snd second
#define mp make_pair
#define squ(x) ((LL)(x) * (x))
#define debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef pair<int, int> pii;

template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }

int sum = 0, fg = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
return fg * sum;
}

const int maxn = 1e5 + 10;
const int inf = 1e9;

int n, a[maxn];

namespace Splay {
int rt;
struct node {
int f, son[2], v, s, sz;
bool rev;
node(): v(inf), s(inf) { }
}A[maxn];
#define ls(x) A[x].son[0]
#define rs(x) A[x].son[1]
#define fa(x) A[x].f
inline void push_up(int x) { A[x].s = min(min(A[ls(x)].s, A[rs(x)].s), A[x].v), A[x].sz = A[ls(x)].sz + A[rs(x)].sz + 1; }
inline void push_down(int x) {
if (A[x].rev) {
swap(ls(x), rs(x));
A[ls(x)].rev ^= 1, A[rs(x)].rev ^= 1, A[x].rev = 0;
}
}
inline bool chk(int x) { return rs(fa(x)) == x; }
inline void link(int x, int y, int f) { fa(x) = y, A[y].son[f] = x; }
inline void rotate(int x) {
int f = fa(x), dx = chk(x), df = chk(f);
push_up(f), push_up(x);
}
inline void splay(int x, int y) {
static int S[maxn]; S[S[0] = 1] = x;
for (int _x = x; _x; _x = fa(_x)) S[++S[0]] = _x;
while (S[0]) push_down(S[S[0]--]);
while (fa(x) != y) { if (fa(fa(x)) != y) rotate(chk(x) == chk(fa(x)) ? fa(x) : x); rotate(x); }
if (!y) rt = x; /**/
}
inline void build(int &x, int l, int r) {
if (l > r) return;
int mid = (l + r) >> 1;
A[x = mid].v = a[mid - 1];
build(ls(x), l, mid - 1), build(rs(x), mid + 1, r);
if (ls(x)) fa(ls(x)) = x;
if (rs(x)) fa(rs(x)) = x;
push_up(x);
}
inline int Rank(int k) {
int x = rt;
while (1) {
push_down(x);
int tot = A[ls(x)].sz + 1;
if (k == tot) break; /**/
if (k < tot) x = ls(x);
else x = rs(x), k -= tot;
}
return x;
}
inline void reverse(int x, int y) {
--x, ++y;
x = Rank(x), y = Rank(y);
splay(x, 0), splay(y, x);
A[ls(y)].rev ^= 1;
}
inline void change(int x) {
x = Rank(x);
A[x].v = inf;
while (x) push_up(x), x = fa(x);
}
inline int query() {
int x = rt, res = 0;
while (ls(x) || rs(x)) {
push_down(x);
if (A[x].v == A[x].s) { res += A[ls(x)].sz; break; } /**/
x = (A[ls(x)].s < A[rs(x)].s ? ls(x) : (res += A[ls(x)].sz + 1, rs(x)));
}
return res + 1;
}
}

int main() {
#ifdef xunzhen
freopen("sort.in", "r", stdin);
freopen("sort.out", "w", stdout);
#endif

static pii p[maxn];
for (int i = 1; i <= n; i++) p[i] = mp(a[i] = read(), i);
sort(p + 1, p + n + 1);
for (int i = 1; i <= n; i++) a[p[i].snd] = i;
a[0] = a[n + 1] = inf;

Splay::build(Splay::rt, 1, n + 2);

for (int i = 2; i <= n + 1; i++) {
int x = Splay::query();
Splay::reverse(i, x);
Splay::change(i);
printf("%d%c", x - 1, i <= n ? ' ' : '\n');
}

return 0;
}
posted @ 2019-02-14 21:51 xunzhen 阅读(...) 评论(...) 编辑 收藏