HDU 1890 Robotic Sort(SplayTree)
来源:互联网 发布:手机淘宝加不了购物车 编辑:程序博客网 时间:2024/05/30 04:35
HDU 1890 Robotic Sort(SplayTree)
http://acm.hdu.edu.cn/showproblem.php?pid=1890
题意:给你N个数,要你执行一系列(题目要求的)翻转操作,使得这N个数按升序排列.要你输出翻转的区间右端点.而且还需要稳定的排序方式.
分析:
假设一棵SplayTree树有n个房间.现在我们将1到n个数放入这n个房间:表示初始的第1到第n个数分别放入了对应的房间了.
在接下来的操作里,只要我们不删除,就算我们rotate,Splay等操作都不会改变第i号房间里面放的数,我们改变的只是其他房间与第i号房间的相对关系.(上面这句好好体会下).我们改变的是pre,ch,root.但是我们改变不了key[i].(此题没用到key数组,但是默认了key[i]=I,表示第i号房间放的是初始数列的第i个数)
所以如果之后我们要找初始序列中的第3个数,我们应该去3号房间找,因为它只要没被删除,肯定在3号房间里面.
下面我们将初始序列稳定排序,然后我们可以得出最小的数在原始数列的第i个位置(也就说明了在SplayTree的i号房间),所以我们Splay(i,0)把它旋转到根部,那么它的左儿子的节点数+1就是当前我们需要翻转的区间右边界.然后对根的左子树执行翻转操作.并且删除根.
接下来我们找第二小的数在原始数列的第j个位置(通过node[2].id=j知道的),所以我们把j号节点翻转到根,执行上一步类似的操作得出这次的区间右边界.
以此类推.该SplayTree需要rev,size,pre,ch 4个信息.本题能不能不删除节点,每次翻转[1,id]这个区间并维护整个数列呢?(比较难,因为你不知道id后面的那个房间是第几号房间,房间的相对位置时刻在变)
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000+100;int n;struct SplayTree{ int pre[maxn],ch[maxn][2],size[maxn],rev[maxn],root; void Update_Rev(int r) { if(r==0) return; rev[r]^=1; swap(ch[r][0],ch[r][1]); } void Push_Down(int r) { if(rev[r]) { Update_Rev(ch[r][0]); Update_Rev(ch[r][1]); rev[r]=0; } } void Push_Up(int r) { size[r]=1+size[ch[r][0]]+size[ch[r][1]]; } void Rotate(int x,int kind) { int y=pre[x]; Push_Down(y); Push_Down(x); ch[y][kind^1]=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; Push_Up(y); } void Splay(int r,int goal) { Push_Down(r); while(pre[r]!=goal) { if(pre[pre[r]]==goal) Rotate(r,ch[pre[r]][0]==r); else { int y=pre[r]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==r) { Rotate(r,kind^1); Rotate(r,kind); } else { Rotate(y,kind); Rotate(r,kind); } } } Push_Up(r); if(goal==0) root=r; } void New_Node(int &r,int fa,int k) { r=k; pre[r]=fa; ch[r][0]=ch[r][1]=rev[r]=0; size[r]=1; } void Build(int &x,int l,int r,int fa) { if(l>r)return ; int mid=(l+r)>>1; New_Node(x,fa,mid); Build(ch[x][0],l,mid-1,x); Build(ch[x][1],mid+1,r,x); Push_Up(x); } void Init() { root=0; ch[root][0]=ch[root][1]=rev[root]=size[root]=pre[root]=0; Build(root,1,n,0); } int Get_Max(int r) { Push_Down(r); while(ch[r][1]) { r=ch[r][1]; Push_Down(r); } return r; } void Remove() { if(ch[root][0]==0) { root=ch[root][1]; pre[root]=0; } else { int m=Get_Max(ch[root][0]); Splay(m,root); ch[m][1]=ch[root][1]; pre[ch[root][1]]=m; root=m; pre[m]=0; Push_Up(root); } }}st;struct Node{ int num; int id; bool operator<(const Node&b)const { if(num==b.num) return id<b.id; return num<b.num; }}nodes[maxn];int main(){ while(scanf("%d",&n)==1&&n) { st.Init(); for(int i=1;i<=n;i++) { scanf("%d",&nodes[i].num); nodes[i].id=i; } sort(nodes+1,nodes+1+n); for(int i=1;i<n;i++) { st.Splay(nodes[i].id,0); st.Update_Rev(st.ch[st.root][0]); printf("%d ",st.size[st.ch[st.root][0]]+i); st.Remove(); } printf("%d\n",n); }}
- HDU 1890 Robotic Sort(SplayTree)
- HDU 1890 Robotic Sort (Splaytree 区间翻转)
- HDU 1890 Robotic Sort
- HDU 1890 Robotic Sort
- hdu 1890 Robotic Sort
- hdu 1890 Robotic Sort
- HDU 1890 Robotic Sort
- hdu-1890 Robotic Sort
- hdu 1890 Robotic Sort(treap)
- 【HDU 1890】Robotic Sort【splay】
- HDU 1890 Robotic Sort [splay]
- HDU 1890 Robotic sort (splay)
- HDU 1890:Robotic Sort Splay
- hdu 1890 Robotic Sort //splay tree
- HDU 1890 Robotic Sort(Splay tree)
- hdu 1890 Robotic Sort(Splay应用)
- hdu 1890 Robotic Sort (Splay树)
- hdu 1890 Robotic Sort(Splay)
- 最短路(Dijstra) A strange lift
- 4.23学习日记
- Android开源工具库
- The OpenGL pipeline
- ios pushViewController 无效果
- HDU 1890 Robotic Sort(SplayTree)
- Spring Xml文件配置实现AOP通知
- 4.24学习日记
- C++、Objective-C 混合编程
- Android popupwindow 失去焦点或者点击空白区域时消失的解决方法
- ubuntu下设置开机启动服务
- 在Ubuntu下如何切换到超级用户
- C# WAV 音频文件处理类 以及 音频转码处理
- 修改UbuntuKylin和Windows共存的GRUB2启动顺序