• [UVA1402]Robotic Sort;[SP2059]CERC07S


    题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成。输出每次操作的$P_i$,要求稳定排序(在括号外的是多组数据,括号内的是单组数据,四倍经验)

    题解:可以用平衡数维护序列,只要维护求一个数的位置和区间翻转即可

    卡点:查询位置时未$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
    ", 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 ? '
    ' : ' ');
    			Treap::reverse(I, res);
    		}
    		scanf("%d", &n);
    		if (n) {
    			Treap::clear();
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    ArcEngine 里面的日期
    ArcEngine连接Oracle数据库
    ArcGIS连接Oracle数据库
    ms sql 带自增列 带外键约束 数据导入导出
    获取指定 MethodInfo 的 MSIL 或者 C# 源码
    架构知识集锦
    ClickOnce手动更新
    委托简单例子
    C# 多线程编程之锁的使用【互斥锁(lock)和读写锁(ReadWriteLock)】
    可扩展类库强制取消异步调用
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9905883.html
Copyright © 2020-2023  润新知