1. 程式人生 > >[UVA1402]Robotic Sort([洛谷P3165][CQOI2014]排序機械臂)

[UVA1402]Robotic Sort([洛谷P3165][CQOI2014]排序機械臂)

題目大意:一串數字,使用如下方式排序: 先找到最小的數的位置$P_1$,將區間$[1,P_1]$反轉,再找到第二小的數的位置$P_2$,將區間$[2,P_2]$反轉,知道排序完成。輸出每次操作的$P_i$,要求穩定排序($UVA$是多組資料,$CQOI$是單組資料)

題解:可以用平衡數維護序列,只要維護求一個數的位置和區間翻轉即可

卡點:查詢位置時未$pushdown$

 

C++ Code:

#include <cstdio>
#include <algorithm>
#define maxn 100010
int n;
int s[maxn], rnk[maxn], mp[maxn];
inline bool cmp(int a, int b) {
	if (s[a] == s[b]) return a < b;
	return s[a] < s[b];
}
namespace Treap {
	int rc[maxn], lc[maxn], pri[maxn], V[maxn], sz[maxn];
	int fa[maxn], tg[maxn];
	int root, idx, ta, tb, tmp, res;
	int seed = 20040826;
	inline int rand() {return seed *= 48271;}
	inline int nw(int x) {
		V[++idx] = x;
		sz[idx] = 1;
		pri[idx] = rand();
		lc[idx] = rc[idx] = fa[idx] = tg[idx] = 0;
		return idx;
	}
	inline int update(int rt) {
		sz[rt] = sz[lc[rt]] + sz[rc[rt]] + 1;
		fa[lc[rt]] = fa[rc[rt]] = rt;
		return rt;
	}
	inline void pushdown(int rt) {
		if (tg[rt]) {
			tg[rt] = 0;
			std::swap(lc[rt], rc[rt]);
			tg[lc[rt]] ^= 1, tg[rc[rt]] ^= 1;
		}
	}
	void split(int rt, int k, int &x, int &y) {
		if (!rt) x = y = 0;
		else {
			pushdown(rt);
			if (sz[lc[rt]] < k) split(rc[rt], k - sz[lc[rt]] - 1, rc[rt], y), x = update(rt);
			else split(lc[rt], k, x, lc[rt]), y = update(rt);
		}
	}
	int merge(int x, int y) {
		if (!x || !y) return x | y;
		pushdown(x), pushdown(y);
		if (pri[x] < pri[y]) {rc[x] = merge(rc[x], y); return update(x);}
		else {lc[y] = merge(x, lc[y]); return update(y);}
	}
	
	void debug(int rt) {
		if (lc[rt]) debug(lc[rt]);
		printf("%d\n", V[rt]);
		if (rc[rt]) debug(rc[rt]);
	}
	
	inline void insert(int x) {
		if (!root) root = nw(x);
		else root = merge(root, nw(x));
	}
	int S[maxn], top;
	inline int gtrnk(int x) {
		top = 0;
		for (int i = x; i; i = fa[i]) S[++top] = i;
		for (; top; top--) pushdown(S[top]);
		res = sz[lc[x]] + 1;
		while (fa[x]) {
			if (rc[fa[x]] == x) res += sz[lc[fa[x]]] + 1;
			x = fa[x];
		}
		return res;
	}
	inline void reverse(int l, int r) {
		if (l > r) std::swap(l, r);
		split(root, r, tmp, tb);
		split(tmp, l - 1, ta, tmp);
		tg[tmp] ^= 1;
		root = merge(ta, merge(tmp, tb));
	}
	inline void clear() {
		idx = root = 0;
	}
}
int main() {
	scanf("%d", &n);
	while (true) {
		if (!n) break;
		for (int i = 1; i <= n; i++) {
			scanf("%d", s + i);
			rnk[i] = i;
		}
		std::sort(rnk + 1, rnk + n + 1, cmp);
		for (int i = 1; i <= n; i++) mp[rnk[i]] = i;
		for (int i = 1; i <= n; i++) Treap::insert(s[i]);
		for (int I = 1, i = rnk[I]; I <= n; i = rnk[++I]) {
			int res = Treap::gtrnk(i);
			printf("%d", res);
			putchar(I == n ? '\n' : ' ');
			Treap::reverse(I, res);
		}
		scanf("%d", &n);
		if (n) {
			Treap::clear();
		}
	}
	return 0;
}