题意:
将一列数字排序 排序规则是 每次找到最小值的位置loc 将1~loc所有数字颠倒 然后删掉第一位 直到排好序 排序要求是稳定的
思路:
这题要做的是 寻找区间最小值位置 翻转区间 的操作 因此可以想到用splay
只需要每个节点记录一个small 就可以实现找到最小值位置
翻转区间操作就是将splay的超级头转到最上面使之成为根 再把loc转到根下面 这时根的右儿子的左儿子就是需要翻转的区间 用一个rev延迟更新 然后将loc转到最上面是指成为根 删掉根 如此循环
注意:
由于翻转区间这种更新会改变树的结构 因此无论是splay的时候还是做任何查找的时候都必须先把rev给down下去!!
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; #define keytree ch[ch[root][1]][0] #define L(x) ch[x][0] #define R(x) ch[x][1] #define N 100010 int n,tot,root; int a[N],ch[N][2],pre[N],size[N],val[N],small[N],rev[N]; void newnode(int &u,int fa,int w) { u=++tot; L(u)=R(u)=0; pre[u]=fa; size[u]=1; small[u]=val[u]=w; rev[u]=0; } void up(int u) { size[u]=size[L(u)]+size[R(u)]+1; small[u]=min(val[u],min(small[L(u)],small[R(u)])); } void down(int u) { if(rev[u]) { if(L(u)) rev[L(u)]^=1; if(R(u)) rev[R(u)]^=1; swap(L(u),R(u)); rev[u]=0; } } void rotate(int u,int kind) { int fa=pre[u]; down(fa); down(u); ch[fa][!kind]=ch[u][kind]; pre[ch[u][kind]]=fa; if(pre[fa]) ch[pre[fa]][ch[pre[fa]][1]==fa]=u; pre[u]=pre[fa]; ch[u][kind]=fa; pre[fa]=u; up(fa); } void splay(int u,int goal) { int fa,kind; down(u); while(pre[u]!=goal) { if(pre[pre[u]]==goal) { down(pre[u]); down(u); rotate(u,L(pre[u])==u); } else { fa=pre[u]; down(pre[fa]); down(fa); down(u); kind=L(pre[fa])==fa; if(ch[fa][kind]==u) { rotate(u,!kind); rotate(u,kind); } else { rotate(fa,kind); rotate(u,kind); } } } up(u); if(goal==0) root=u; } int getkth(int u,int k) { down(u); int s=size[L(u)]+1; if(s==k) return u; if(s>k) return getkth(L(u),k); else return getkth(R(u),k-s); } void build(int &u,int l,int r,int fa) { if(l>r) return ; int mid=(l+r)>>1; newnode(u,fa,a[mid]); build(L(u),l,mid-1,u); build(R(u),mid+1,r,u); up(u); } void init() { root=tot=0; L(root)=R(root)=pre[root]=size[root]=rev[root]=0; val[root]=small[root]=N; newnode(root,0,N); newnode(R(root),root,N); build(keytree,1,n,R(root)); up(R(root)); up(root); } int getmin(int u,int x) { down(u); if(val[u]==x) return 1+size[L(u)]; if(small[L(u)]==x) return getmin(L(u),x); if(small[R(u)]==x) return size[L(u)]+1+getmin(R(u),x); } int getpre(int u) { down(u); u=L(u); down(u); while(R(u)) { u=R(u); down(u); } return u; } void remove() { if(L(root)) { int i=getpre(root); splay(i,root); R(i)=R(root); pre[R(root)]=i; root=L(root); pre[root]=0; up(root); } else { root=R(root); pre[root]=0; } } struct input { int val,id; bool operator<(const input fa) const { if(val==fa.val) return id<fa.id; return val<fa.val; } }fzc[N]; int main() { int i,loc; while(~scanf("%d",&n)) { if(!n) break; for(i=1;i<=n;i++) { scanf("%d",&fzc[i].val); fzc[i].id=i; } sort(fzc+1,fzc+n+1); for(i=1;i<=n;i++) a[fzc[i].id]=i; init(); for(i=1;i<n;i++) { loc=getmin(root,i); printf("%d ",loc+i-2); splay(getkth(root,1),0); splay(getkth(root,loc),root); rev[keytree]^=1; splay(getkth(root,loc),0); remove(); } printf("%d\n",n); } return 0; }
HDU 1890 Robotic Sort,布布扣,bubuko.com
原文地址:http://blog.csdn.net/houserabbit/article/details/37901199