洛谷P3165 排序机械臂 splay
网址:https://www.luogu.org/problem/P3165
题意:
每一次先输出$pos_i$翻转$[i,pos_i]$,$pos_i$为$i$在当前序列上的位置。
题解:
$splay$维护序列。原理是维护中序遍历,具有的性质是$splay$的节点编号一一对应序列上的各个位置的关键字,由于本题中,高度会有相同值,所以以序列的位置为关键字,该关键字和$splay$上的节点编号一一对应建立双射。然后$pos_i$就可以直接找到其在$splay$上的节点编号,把该编号旋到根,就可以求出其权值,然后打翻转标记即可。
AC代码:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; struct node { int val, pos; node() {}; node(int _val, int _pos) :val(_val), pos(_pos) {}; }; node a[MAXN]; bool cmp(node& a, node& b) { return a.val < b.val || (a.val == b.val && a.pos < b.pos); } int hs[MAXN]; struct Splay { int fa[MAXN], son[MAXN][2], val[MAXN], size[MAXN]; int tag[MAXN]; int rt, sz; void pushdown(int x) { if (tag[x]) { tag[son[x][0]] ^= 1; tag[son[x][1]] ^= 1; tag[x] = 0; swap(son[x][0], son[x][1]); } } void pushup(int x) { if (x) { size[x] = 1; if (son[x][0]) size[x] += size[son[x][0]]; if (son[x][1]) size[x] += size[son[x][1]]; } } int getson(int x) { return son[fa[x]][1] == x; } void con(int x, int y, int z) { if (x) fa[x] = y; if (y) son[y][z] = x; } void rotate(int x) { int fx = fa[x], ffx = fa[fx]; int fs = getson(x), ffs = getson(fx); con(son[x][fs ^ 1], fx, fs); con(fx, x, fs ^ 1); con(x, ffx, ffs); pushup(fx); } void splay(int x, int end) { end = fa[end]; int f; pushdown(x); while (fa[x] != end) { f = fa[x]; pushdown(fa[f]), pushdown(f), pushdown(x); if (fa[f] != end) rotate(getson(f) == getson(x) ? f : x); rotate(x); } pushup(x); if (!end) rt = x; } int newnode(int x, int f) { int root = ++sz; fa[root] = f; son[root][0] = son[root][1] = 0; size[root] = 1; tag[root] = 0; val[root] = x; return root; } int build(int f, int l, int r) { if (l > r) return 0; int m = (l + r) >> 1; int tmp = newnode(a[m].val, f); hs[a[m].pos] = tmp; son[tmp][0] = build(tmp, l, m - 1); son[tmp][1] = build(tmp, m + 1, r); pushup(tmp); return tmp; } int querynum(int x) { int now = rt; while (x) { pushdown(now); if (son[now][0] && x <= size[son[now][0]]) { now = son[now][0]; continue; } if (son[now][0]) x -= size[son[now][0]]; if (x == 1) { splay(now, rt); return now; } x -= 1; now = son[now][1]; } return -1; } void reverse(int ql, int qr) { int l = querynum(ql - 1), r = querynum(qr + 1); splay(l, rt), splay(r, son[l][1]); tag[son[r][0]] ^= 1; } void solve(int i, int pos) { int trp = hs[pos]; splay(trp, rt); int rnk = size[son[rt][0]]; printf("%d ", rnk); reverse(i, rnk + 1); } void init() { rt = sz = 0; } }; Splay sp; int main() { int n; scanf("%d", &n); a[1] = node(0, 1); a[n + 2] = node(1e7 + 5, n + 2); for (int i = 2; i <= n + 1; ++i) scanf("%d", &a[i].val), a[i].pos = i; sp.init(); sp.rt = sp.build(0, 1, n + 2); sort(a + 1, a + n + 3, cmp); for (int i = 2; i <= n + 1; ++i) sp.solve(i, a[i].pos); printf("\n"); return 0; }