P3165 [CQOI2014]排序机械臂
P3165 [CQOI2014]排序机械臂
题目描述
为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序;第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序。
上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序;第二次操作前,第二低的物品在位罝6,于是把第2至6的物品反序...
你的任务便是编写一个程序,确定一个操作序列,即每次操作前第i低的物品所在位置Pi,以便机械臂工作。需要注意的是,如果有高度相同的物品,必须保证排序后它们的相对位置关系与初始时相同。
输入输出格式
输入格式:
第一行包含正整数n,表示需要排序的物品数星。
第二行包含n个空格分隔的整数ai,表示每个物品的高度。
输出格式:
输出一行包含n个空格分隔的整数Pi。
输入输出样例
code
神奇的splay
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 500100; 7 const int INF = 1e9; 8 9 int data[N],siz[N],mn[N],pos[N],tag[N],ch[N][2],fa[N],st[N]; 10 int Root,top; 11 12 struct Data{ 13 int x,p; 14 }d[N]; 15 16 inline char nc() { 17 static char buf[100000],*p1 = buf,*p2 = buf; 18 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++; 19 } 20 inline int read() { 21 int x = 0,f = 1;char ch = nc(); 22 for (; ch<'0'||ch>'9'; ch = nc()) 23 if (ch=='-') f = -1; 24 for (; ch>='0'&&ch<='9'; ch = nc()) 25 x = x * 10 + ch - '0'; 26 return x * f; 27 } 28 bool cmp1(Data a,Data b) { 29 if (a.x==b.x) return a.p < b.p; 30 return a.x < b.x; 31 } 32 bool cmp2(Data a,Data b) { 33 return a.p < b.p; 34 } 35 inline void pushup(int x) { 36 int l = ch[x][0],r = ch[x][1]; 37 mn[x] = data[x],pos[x] = x; 38 if (mn[l] < mn[x]) mn[x] = mn[l],pos[x] = pos[l]; 39 if (mn[r] < mn[x]) mn[x] = mn[r],pos[x] = pos[r];//- 40 siz[x] = siz[l] + siz[r] + 1; 41 } 42 inline void pushdown(int x) { 43 if (tag[x]) { 44 tag[ch[x][0]] ^= 1; 45 tag[ch[x][1]] ^= 1; 46 swap(ch[x][0],ch[x][1]); 47 tag[x] ^= 1; 48 } 49 } 50 inline int son(int x) { 51 return x == ch[fa[x]][1]; //- 52 } 53 inline void rotate(int x) { 54 int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b]; 55 if (z) ch[z][c] = x;else Root = x;fa[x] = z; //- 56 ch[x][!b] = y;fa[y] = x; 57 ch[y][b] = a;if (a) fa[a] = y; 58 pushup(y);pushup(x); 59 } 60 inline void splay(int x,int rt) { 61 top = 0;int p = x;//-- 62 while (p) st[++top] = p,p = fa[p]; 63 while (top) pushdown(st[top]),top--; 64 while (fa[x] != rt) { 65 int y = fa[x],z = fa[y]; 66 if (z==rt) rotate(x); 67 else { 68 if (son(x)==son(y)) rotate(y),rotate(x); 69 else rotate(x),rotate(x); 70 } 71 } 72 } 73 inline int getkth(int k) { 74 int p = Root; 75 while (true) { 76 pushdown(p); 77 if (k == siz[ch[p][0]] + 1) return p; 78 if (ch[p][0] && siz[ch[p][0]] >= k) p = ch[p][0]; 79 else { 80 k -= ((ch[p][0] ? siz[ch[p][0]] : 0) + 1); 81 p = ch[p][1]; 82 } 83 } 84 } 85 inline int getmnpos(int l,int r) { 86 int L = getkth(l),R = getkth(r+2); 87 splay(L,0); 88 splay(R,L); 89 return pos[ch[R][0]]; 90 } 91 inline void rever(int l,int r) { 92 int L = getkth(l),R = getkth(r+2); 93 splay(L,0);splay(R,L); 94 tag[ch[R][0]] ^= 1; 95 } 96 int build(int l,int r) { 97 if (l > r) return 0; 98 /*if (l==r) { 99 siz[l] = 1;data[l] = mn[l] = d[l].x;pos[l] = l; 100 return l; 101 }*/ 102 int mid = (l + r) >> 1; 103 int t = build(l,mid-1); 104 fa[t] = mid;ch[mid][0] = t; 105 t = build(mid+1,r); 106 fa[t] = mid;ch[mid][1] = t; 107 data[mid] = d[mid].x; //= mn[mid]pos[mid] = mid; 108 pushup(mid); 109 return mid; 110 } 111 112 int main() { 113 int n = read(); 114 d[1].x = d[n+2].x = mn[0] = INF; 115 for (int i=2; i<=n+1; ++i) 116 d[i].x = read(),d[i].p = i; 117 sort(d+2,d+n+2,cmp1); 118 for (int i=2; i<=n+1; ++i) 119 d[i].x = i - 1; // 没有相等的 120 sort(d+2,d+n+2,cmp2); 121 Root = build(1,n+2); 122 for (int i=1; i<=n; ++i) { 123 int x = getmnpos(i,n); 124 splay(x,0); 125 printf("%d ",siz[ch[x][0]]); // siz[ch[x][0]] + 1 - 1 126 rever(i,siz[ch[x][0]]); 127 } 128 return 0; 129 }