【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂

Splay



  离散化+Splay维护序列……

  好吧主要说一下我做这道题遇到的几个错误点:

  1.离散化

  2.由于找到的这个数的位置一定是大于等于 i 的,所以其实在把它splay到根以后,i 结点只能splay到它的左儿子,而不是右儿子……而且相应的,代表这个区间的应该是c[c[root][0]][1]呃……就是root的左儿子的右儿子= =整个反了一下……好吧不要在意这些细节,我也不知道为什么我突然要反过来写[捂脸熊]

  3.进行了修改操作以后一定要立即splay修改的结点!在这题中就是当找到最小结点,将其置为无穷大后,一定要splay一下……否则就WA了TAT

  1 /**************************************************************
  2     Problem: 1552
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:2764 ms
  7     Memory:4888 kb
  8 ****************************************************************/
  9
 10 //BZOJ 1552
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;i--)
 19 using namespace std;
 20 typedef long long LL;
 21 inline int getint(){
 22     int r=1,v=0; char ch=getchar();
 23     for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1;
 24     for(; isdigit(ch);ch=getchar()) v=v*10+ch-‘0‘;
 25     return r*v;
 26 }
 27 const int N=1e5+10,INF=~0u>>2;
 28 /******************template*********************/
 29 struct node{int v,pos;}a[N];
 30 bool operator < (node a,node b){return a.pos<b.pos;}
 31 bool cmp(node a,node b){return a.v<b.v||(a.v==b.v && a.pos<b.pos);}
 32 int c[N][2],fa[N],v[N],mn[N],size[N],tot,root,n;
 33 bool rev[N];
 34 #define L c[x][0]
 35 #define R c[x][1]
 36 void Push_down(int x){
 37     if (rev[x]){
 38         rev[L]^=1; rev[R]^=1;
 39         swap(L,R); rev[x]=0;
 40     }
 41 }
 42 void Push_up(int x){
 43     mn[x]=v[x];
 44     if (L) mn[x]=min(mn[x],mn[L]);
 45     if (R) mn[x]=min(mn[x],mn[R]);
 46     size[x]=size[L]+size[R]+1;
 47 }
 48 void Rotate(int x){
 49     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
 50     c[z][c[z][1]==y]=x;
 51     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
 52     c[y][l]=c[x][r]; c[x][r]=y;
 53     Push_up(y);
 54 }
 55 int st[N];
 56 void Preview(int x){
 57     int top=0; st[++top]=x;
 58     for(int i=x;fa[i];i=fa[i])
 59         st[++top]=fa[i];
 60     D(i,top,1) Push_down(st[i]);
 61 }
 62 void splay(int x,int s=0){
 63     int y;
 64     for(Preview(x);fa[x]!=s;Rotate(x))
 65         if (fa[y=fa[x]]!=s) Rotate(c[y][1]==x^c[fa[y]][1]==y?x:y);
 66     Push_up(x);
 67     if (!s) root=x;
 68 }
 69 void New_node(int &x,int f,int key){
 70     x=++tot;
 71     fa[x]=f;
 72     v[x]=mn[x]=key;
 73     rev[x]=L=R=0;
 74     size[x]=1;
 75 }
 76 void Build(int &x,int f,int l,int r){
 77     if (l>r) return;
 78     int mid=l+r>>1;
 79     New_node(x,f,a[mid].v);
 80     Build(L,x,l,mid-1);
 81     Build(R,x,mid+1,r);
 82     Push_up(x);
 83 }
 84 int kth(int x,int k){
 85     Push_down(x);
 86     if (size[L]+1==k) return x;
 87     else if (size[L]>=k) return kth(L,k);
 88     else return kth(R,k-size[L]-1);
 89 }
 90 int findmin(int x){
 91     Push_down(x);
 92     if (L && mn[x]==mn[L]) return findmin(L);
 93     else if (R && mn[x]==mn[R]) return findmin(R)+size[L]+1;
 94     else {v[x]=INF;Push_up(x); return size[L]+1;}
 95 }
 96 int main(){
 97     n=getint();
 98     v[0]=mn[0]=a[0].v=a[n+1].v=INF;
 99     F(i,1,n) {a[i].v=getint();a[i].pos=i;}
100     sort(a+1,a+n+1,cmp);
101     F(i,1,n) a[i].v=i;
102     sort(a+1,a+n+1);
103     Build(root,0,0,n+1);
104     F(i,1,n){
105         int t1=findmin(root);
106         splay(kth(root,t1));
107         printf("%d",t1-1); if(i!=n)printf(" ");
108         splay(kth(root,t1+1)); splay(kth(root,i),root);
109         int pos=c[c[root][0]][1];
110         if (pos) rev[pos]^=1;
111         splay(pos);
112     }
113     return 0;
114 }
115 

1552: [Cerc2007]robotic sort

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 436  Solved: 186
[Submit][Status][Discuss]

Description

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,(1 < = Pi < = N),Pi表示第i次操作前第i小的物品所在的位置。
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6

HINT

Source

HNOI2009集训Day6

[Submit][Status][Discuss]

时间: 2024-10-19 23:53:28

【BZOJ】【1552】【Cerc2007】robotic sort / 【3506】【CQOI2014】排序机械臂的相关文章

[bzoj1552][Cerc2007]robotic sort&amp;&amp;[bzoj3506][Cqoi2014]排序机械臂

非常垃圾的一道平衡树,结果被日了一天.很难受嗷嗷嗷 首先不得不说网上的题解让我这个本来就不熟悉平衡树的彩笔很难受--并不好理解. 还好Sinogi大佬非常的神,一眼就切掉了,而且用更加美妙的解法. 题意在操作时,就是第i次把编号为i-1和编号i的后继分别提到根和根的右儿子,根的右儿子的左子树打上翻转标记. 用外部数组记录原来高度第几大的在平衡树中编号是多少.就可以直接操作了. 注意有相同的高度,离散化时直接按高度第一关键字,编号第二关键字就行了. 还有每次splay要把根到当前节点都pushdo

BZOJ 1552: [Cerc2007]robotic sort( splay )

kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经验 ) ----------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #inclu

bzoj 1552: [Cerc2007]robotic sort.

1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1211  Solved: 463[Submit][Status][Discuss] Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. 第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. Output 输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次

1552: [Cerc2007]robotic sort

1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1205  Solved: 459 Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. 第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. Output 输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置. 注意:如果第i次操

[CQOI2014]排序机械臂

洛谷P3165 [CQOI2014]排序机械臂 https://www.luogu.org/problem/show?pid=3165 题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序. 上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序:第二次

P3165 [CQOI2014]排序机械臂

P3165 [CQOI2014]排序机械臂 题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序. 上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序:第二次操作前,第二低的物品在位罝6,于是把第2至6的物品反序... 你的任务便是编写一个程序,确定

Luogu P3165 [CQOI2014]排序机械臂

先讲一下和这题一起四倍经验的题: Luogu P4402 [Cerc2007]robotic sort 机械排序 SP2059 CERC07S - Robotic Sort UVA1402 Robotic Sort 这题作为一道十分经典的平衡树维护序列的问题,自然是值得一做的了. 写完翻了下题解发现都是写Splay的dalao,少有的暴力FHQ_Treap党还是用指针实现的. 所以这里略微讲解下数组实现的FHQ_Treap好了,感觉写起来比Splay舒服些. 首先我们要抽象化一下题意:给你\(n

洛谷P3165 [CQOI2014]排序机械臂

题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂.它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序:第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序. 上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序:第二次操作前,第二低的物品在位罝6,于是把第2至6的物品反序... 你的任务便是编写一个程序,确定一个操作序列,即每次操作前第i低的物品所在位

[BZOJ3506] [Cqoi2014] 排序机械臂 (splay)

Description 同OJ1552 Input Output Sample Input Sample Output HINT Source Solution Q:哎不是同一道题吗为什么分两篇博客来写? A:当然是来骗浏览量了233333333,这里还是会放代码的,当然你左转BZOJ1552的题解也行. 1 #include <bits/stdc++.h> 2 using namespace std; 3 struct spaly 4 { 5 int c[2], fa, siz, rev;