题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$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\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;
}

  

最新文章

  1. js快速判断IE浏览器(兼容IE10与IE11)
  2. TCP重传率高的监控
  3. HDU 5980 Find Small A(寻找小A)
  4. python 核心编程课后练习(chapter 3)
  5. DEBUG STACK TRACE for PoolBackedDataSource.close().
  6. R语言描述性统计常用函数
  7. Python支持中文注释
  8. 推荐:ThoughtWorks(中国)程序员读书雷达
  9. (Relax DFS专题1.2)POJ 2386 Lake Counting(使用DFS来计算有多少坨东西是连通的)
  10. MSSQL - 因为数据库正在使用,所以无法获得对数据库的独占访问权。
  11. 循环获取json对象的属性名
  12. CISCO2960配置vlan
  13. visual studio 各版本激活码
  14. UDP广播 MAC地址
  15. Javascript中表达式和语句的区别
  16. JS创建对象之原型模式
  17. B. Array
  18. P4281 [AHOI2008]紧急集合 / 聚会
  19. Java实现哈夫曼编码和解码
  20. Zabbix添加自定义监控项(一)

热门文章

  1. js根据年份获取某月份有几天
  2. 2017年PHP程序员未来路在何方?(转载)
  3. MySQL必会
  4. hadoop生态搭建(3节点)-01.基础配置
  5. 宝塔漏洞 XSS窃取宝塔面板管理员漏洞 高危
  6. ADB工具的安装
  7. Jersey2+swagger组建restful风格api及文档管理
  8. 当应用出现 access violation at address in module时
  9. android中接入twitter进行第三方登录
  10. Android2.2以上的版本HttpURLConnection.getContentLength()获取的size跟下载下来的file的legth不相等