舒展树(splay tree)学习三:hdu1890 Robotic Sort
伸展树(splay tree)学习三:hdu1890 Robotic Sort
题目大意:给你n个数,每次将第i个位置到第i大的数所在位置 之间的数进行翻转,输出的是第i大的数所在的位置
题目大意:给你n个数,每次将第i个位置到第i大的数所在位置 之间的数进行翻转,输出的是第i大的数所在的位置
伸展树的节点编号的相对大小代表的是这个数在数组中的下标,并记录下第i大的数所在的节点编号是什么。
最后每次将第i大的数旋转到根,然后 左子树的大小 就是在数组中相对位置在这个数的左边的数的个数 因为每次将第i大的数翻转到第i个位置时,这个数就不会用到了,
所以每次统计好后就直接把根节点给删了,这样的话答案就是 i+size[ch[root][0]] 。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define N 100015 #define inf 1<<29 #define LL long long using namespace std; struct node{ int num,rank; }a[N]; int pre[N],ch[N][2],root,tot; //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量 int size[N]; int rev[N]; int n,q; inline void Newnode(int &r,int father,int k) { r=k; pre[r]=father; rev[r]=0; size[r]=1; ch[r][0]=ch[r][1]=0; //左右孩子为空 } inline void Push_Down(int r)//将延迟标记更新到孩子结点 { if(rev[r]) { rev[ch[r][0]]^=1; rev[ch[r][1]]^=1; swap(ch[r][0],ch[r][1]); rev[r]=0; } } inline void Push_Up(int r)//通过孩子结点更新父结点 { size[r]=size[ch[r][0]]+size[ch[r][1]]+1; } inline void Rotate(int x,int kind) { int y=pre[x]; Push_Down(y); Push_Down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; pre[x]=pre[y]; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; ch[x][kind]=y; pre[y]=x; Push_Up(y); } inline void Splay(int x,int goal) { Push_Down(x); while (pre[x]!=goal) { int y=pre[x],z=pre[y]; Push_Down(z); Push_Down(y); Push_Down(x); if (pre[pre[x]]==goal) Rotate(x,ch[pre[x]][0] == x); else { if (ch[z][0] == y) if (ch[y][0] == x) Rotate(y, 1), Rotate(x, 1); else Rotate(x, 0), Rotate(x, 1); else if (ch[y][0] == x) Rotate(x, 1), Rotate(x, 0); else Rotate(y, 0), Rotate(x, 0); } } Push_Up(x); if (goal == 0) root=x; } inline void RotateTo(int k,int goal) //把第k位的数转到goal下边 { int r=root; Push_Down(r); while ((size[ch[r][0]]+1)!=k) { if (k <= size[ch[r][0]]) r=ch[r][0]; else { k-=(size[ch[r][0]]+1); r=ch[r][1]; } Push_Down(r); } Splay(r,goal); } inline void Del_root()//删除根节点 { int t=root; if(ch[root][1]) { root=ch[root][1]; RotateTo(1,0);//把右子树中序遍历的第一个点旋转到根(因为这个点的左儿子肯定为空) ch[root][0]=ch[t][0];//将原先根节点的左子树接到当前根节点的左子树上 if(ch[t][0]) pre[ch[t][0]]=root; } else root=ch[root][0]; pre[root]=0; Push_Up(root); } inline void Build(int &x,int l,int r,int fa) { if (l > r) return; int mid=(l + r) >> 1; Newnode(x,fa,mid); Build(ch[x][0],l,mid-1,x); Build(ch[x][1],mid+1,r,x); Push_Up(x); } bool cmp(node a,node b) { if (a.num!=b.num) return a.num<b.num; else return a.rank<b.rank; } inline void Init() { for (int i=1; i<=n; i++) { scanf("%d",&a[i].num); a[i].rank=i; } sort(a+1,a+n+1,cmp); ch[0][0]=ch[0][1]=pre[0]=size[0]=rev[0]=0; root=tot=0; Build(root,1,n,0); } int main() { while (scanf("%d",&n)!=EOF && n) { Init(); for (int i=1; i<n; i++) { Splay(a[i].rank,0); rev[ch[root][0]]^=1; printf("%d ",i+size[ch[root][0]]); Del_root(); } printf("%d\n",n); } return 0; }