博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Luogu4402 机械排序
阅读量:5095 次
发布时间:2019-06-13

本文共 3933 字,大约阅读时间需要 13 分钟。

Description

给你一个长度为\(n\)的序列,你要对它进行操作,规则如下

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

最后输出操作序列\(p_i\)

Solution

很久没有做过\(Splay\)的题目了,来打个板子复习一下

我们可以把题意转换一下:第\(i\)次操作时,找到区间\([i, n]\)中最小的数的位置\(p_i\),并翻转区间\([i, p_i]\)

然后这相当于就是一个排序 虽然我没用这个做法

我的做法特别简单粗暴,就是照着题意模拟

每次直接找整段区间最小值的位置,然后用\(Splay\)模拟题目的翻转,然后把这个最小值设为\(inf\)

\(p_i​\)序列就边操作边输出就可以了

Code

#include 
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
pii;template
inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }template
inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }inline int read() { 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); link(A[x].son[dx ^ 1], f, dx); link(x, fa(f), df); link(f, x, dx ^ 1); 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]; n = read(); 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;}

转载于:https://www.cnblogs.com/xunzhen/p/10380973.html

你可能感兴趣的文章
sgu 160 Magic Multiplying Machine
查看>>
24 款必备的 Linux 桌面应用(2016 版)
查看>>
Netty中的ChannelHandler
查看>>
bash 设置
查看>>
改变字符串里面多个颜色
查看>>
POJ 2195 Going Home【最小费用最大流】
查看>>
MySQL 用户权限管理
查看>>
windows下的DeepLearning环境搭建:Theano的安装
查看>>
C++ vector 用法
查看>>
责任链模式 详解
查看>>
LRU算法总结
查看>>
236. 二叉树的最近公共祖先
查看>>
IOCTL错误
查看>>
yii2购物车实现
查看>>
[CQOI2014]危桥
查看>>
Hsqldb在Memory-Only模式下方便发布项目
查看>>
编写高质量代码改善C#程序的157个建议——建议65:总是处理未捕获的异常
查看>>
JS面向对象
查看>>
基于Python对象引用、可变性和垃圾回收详解
查看>>
放大镜一:图片上部添加可移动遮盖层
查看>>