BZOJ 1552/1506 [Cerc2007]robotic sort
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1552
【分析】
这题哇!又有翻转操作...每次要输出第几个?是吧...
所以又要用Splay了。
可是这道题有创新的地方,因为又有数值上的有序[取最小值],又有位置上的有序[翻转和求第几个]
可是毕竟最小值的操作会简单很多...所以我们采用的是将位置作为Splay的节点信息。
那么怎么快速得到最小值的位置呢?当然就是常用的push_up了...向上更新就好了。
这里一定要注意题目所说:按照刚开始给你的顺序排序,在实现中就是数组的下标了,每次还需要比较两边最优值的大小和下标。
然后每次选出最小值,将其转到树根,输出其左子树的大小+已经删去的最小值数目,然后将它删去,从左子树中选一个最右边的节点翻到顶上,作为新的节点。
大致过程就是这样啦...【表示都是笔者想出来的...很开心啊...只是速度还是没有某人快啊...】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline int in(){ int x=0,f=1;char ch=getchar(); while((ch>'9' || ch<'0') && ch!='-') ch=getchar(); if(ch=='-') f=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } const int maxn=100010; const int INF=0x7f7f7f7f; struct Node{ int ch[2],f; int sz,mn,lc,dt; bool rv; }s[maxn]; int n,rt; int a[maxn]; void push_down(int x){ if(s[x].rv){ swap(s[x].ch[0],s[x].ch[1]); s[s[x].ch[0]].rv^=1,s[s[x].ch[1]].rv^=1; s[x].rv=0; } } void update(int x){ s[x].sz=s[s[x].ch[0]].sz+s[s[x].ch[1]].sz+1; s[x].mn=s[x].dt,s[x].lc=x; int l,r;l=s[x].ch[0],r=s[x].ch[1]; if((s[l].mn<s[x].mn) || (s[l].mn==s[x].mn && s[l].lc<s[x].lc)) s[x].mn=s[l].mn,s[x].lc=s[l].lc; if((s[r].mn<s[x].mn) || (s[r].mn==s[x].mn && s[r].lc<s[x].lc)) s[x].mn=s[r].mn,s[x].lc=s[r].lc; } int build(int l,int r){ if(l>r) return 0; int mid=(l+r)>>1; s[mid].ch[0]=build(l,mid-1); s[mid].ch[1]=build(mid+1,r); if(s[mid].ch[0]) s[s[mid].ch[0]].f=mid; if(s[mid].ch[1]) s[s[mid].ch[1]].f=mid; s[mid].dt=a[mid]; update(mid); return mid; } void Rotate(int x,int k){ int y=s[x].f;s[x].f=s[y].f; if(s[y].f) s[s[y].f].ch[y==s[s[y].f].ch[1]]=x; s[y].ch[k]=s[x].ch[k^1]; if(s[x].ch[k^1]) s[s[x].ch[k^1]].f=y; s[y].f=x,s[x].ch[k^1]=y; update(y),update(x); } void Splay(int x,int gf){ int y; while(s[x].f!=gf){ y=s[x].f; if(s[y].f==gf) Rotate(x,x==s[y].ch[1]); else{ int z=s[y].f; if(y==s[z].ch[0]){ if(x==s[y].ch[0]) Rotate(y,0),Rotate(x,0);else Rotate(x,1),Rotate(x,0);} else{ if(x==s[y].ch[1]) Rotate(y,1),Rotate(x,1);else Rotate(x,0),Rotate(x,1);} } } if(!gf) rt=x; } int Find_right(int x){ int p=x,f=-1; while(p){ push_down(p); f=p;p=s[f].ch[1]; } return f; } int st[maxn],tp; void up_push_down(int x){ int p=x; while(p) st[++tp]=p,p=s[p].f; while(tp) push_down(st[tp--]); } int main(){ #ifndef ONLINE_JUDGE freopen("1552.in","r",stdin); freopen("1552.out","w",stdout); #endif n=in(); for(int i=1;i<=n;i++) a[i]=in(); s[0].mn=INF;s[0].lc=-1; rt=build(1,n); int x; for(int i=1;i<=n;i++){ up_push_down(s[rt].lc); Splay(s[rt].lc,0); printf("%d",s[s[rt].ch[0]].sz+i); if(i!=n) printf(" "); s[s[rt].ch[0]].rv^=1; if(!s[rt].ch[0]){ s[s[rt].ch[1]].f=0;rt=s[rt].ch[1]; } else{ x=Find_right(s[rt].ch[0]); Splay(x,rt); s[x].f=0; s[x].ch[1]=s[rt].ch[1]; if(s[rt].ch[1]) s[s[rt].ch[1]].f=x; update(x);rt=x; } } return 0; }