Robotic Sort
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
Output
Sample Input
6 3 4 5 1 6 2 4 3 3 2 1 0
Sample Output
4 6 4 5 6 6 4 2 4 4 题意很明确,就是要你每次找最小数字位置,翻转整个区间,达到排序的目的,相同的数字按下标小的优先。 分析:伸展树的区间翻转操作和删除根节点操作,每次将最小的那个数的编号放到根节点,那么根节点的左儿子的siz+1就是当前的位置,然后在左树递归 查找到一个根节点的可替代节点,替换当前的根节点即可。 注意在splay时先判断父节点是否可翻转在执行当前旋转操作,不然会出错。 源代码在加入了inline之后活生生少了100+ms,不可思议#include<cstring> #include<string> #include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<map> #include<cstdlib> #include<cmath> #include<vector> //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f #define maxn 100005 #define keytree (ch[ch[root][1]][0]) int e[maxn],tmp[maxn]; int siz[maxn],ch[maxn][2],rev[maxn],pre[maxn],id[maxn]; int root,top; bool cmp(int a,int b) { if(tmp[a]!=tmp[b]) return tmp[a]<tmp[b]; return a<b; } inline void newnode(int &x,int p) { x=++top; siz[x]=1; ch[x][0]=ch[x][1]=0; pre[x]=p; rev[x]=0; } inline void pushup(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } inline void pushdown(int x) { if(rev[x]) { swap(ch[x][0],ch[x][1]); rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]=0; } } inline void build(int &x,int l,int r,int p) { int mid=(l+r)>>1; newnode(x,p); id[mid]=top; if(l<mid) build(ch[x][0],l,mid-1,x); if(r>mid) build(ch[x][1],mid+1,r,x); pushup(x); } inline void init(int n) { root=1; top=0; siz[0]=ch[0][0]=ch[0][1]=pre[0]=rev[0]=0; build(ch[0][1],0,n-1,0); } inline void Rotate(int x,int kind) { int y=pre[x]; pushdown(y); pushdown(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; pushup(y); } inline void splay(int x,int goal) { while(pre[x]!=goal) { if(pre[pre[x]]==goal) { pushdown(pre[x]); pushdown(x); Rotate(x,ch[pre[x]][0]==x); } else { pushdown(pre[pre[x]]); pushdown(pre[x]); pushdown(x); int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) { Rotate(x,!kind); Rotate(x,kind); } else { Rotate(y,kind); Rotate(x,kind); } } } pushup(x); if(goal==0) root=x; } inline void find_left(int x) { pushdown(x); siz[x]--; if(ch[x][1]==0) { int kind=ch[pre[x]][1]==x; pre[ch[x][0]]=pre[x]; ch[pre[x]][kind]=ch[x][0]; ch[x][0]=ch[root][0]; ch[x][1]=ch[root][1]; pre[ch[x][0]]=pre[ch[x][1]]=x; pre[x]=0; root=x; pushup(x); } else find_left(ch[x][1]); } inline int update(int r) { splay(r,0); int ans=siz[ch[r][0]]+1; rev[ch[r][0]]^=1; if(ch[r][0]==0) { ch[0][1]=ch[r][1]; pre[ch[r][1]]=0; } else find_left(ch[r][0]); return ans; } int main() { int n; while(scanf("%d",&n)!=EOF&&n) { for(int i=0; i<n; i++) scanf("%d",&tmp[i]),e[i]=i; init(n); sort(e,e+n,cmp); for(int i=0; i<n; i++) { int r=id[e[i]]; int ans; ans=update(r); printf("%d%c",ans+i,i==n-1?'\n':' '); } } return 0; }