HDU1890 Robotic Sort SPLAY

这道题目需要伸展树的区间翻转操作,另外这道题我完成了我的SPLAY的删除节点的操作,由于伸展树的操作特点,删除某个节点的步骤是将该节点旋转到root然后再删除,也就是啊说,我们只要写个删除根节点的函数即可。

另外注意push_down的位置。

感想:伸展树真的很漂亮,这些操作都很神奇

 

解法:

题目意思是我们要将所有试管从低到高排序,刚开始试管是无序的。因此需要一个机械手臂从低到高抓取相应的试管然后和他对应位置上的试管交换位置。

要求从低到高每个试管的位置。(注意这里的位置是动态变化的,加入我现在放高度为i的试管那么我要将第i到pos【i】这个区间的所有试管位置翻转,着用到了伸展树的区间翻转。)然后求出高度为i的试管在那个坐标。

由于每次求出一个位置相应删除节点,那么第i高的试管位置等于讲i旋转到根部后他左子树的size加上i。

注意:建树方法很特殊,因为使用递归建树可以保证深度最小。

 

Robotic Sort

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1407    Accepted Submission(s): 594


Problem Description
Somewhere deep in the Czech Technical University buildings, there are laboratories for examining mechanical and electrical properties of various materials. In one of yesterday’s presentations, you have seen how was one of the laboratories changed into a new multimedia lab. But there are still others, serving to their original purposes.

In this task, you are to write software for a robot that handles samples in such a laboratory. Imagine there are material samples lined up on a running belt. The samples have different heights, which may cause troubles to the next processing unit. To eliminate such troubles, we need to sort the samples by their height into the ascending order.

Reordering is done by a mechanical robot arm, which is able to pick up any number of consecutive samples and turn them round, such that their mutual order is reversed. In other words, one robot operation can reverse the order of samples on positions between A and B.

A possible way to sort the samples is to find the position of the smallest one (P1) and reverse the order between positions 1 and P1, which causes the smallest sample to become first. Then we find the second one on position P and reverse the order between 2 and P2. Then the third sample is located etc.



The picture shows a simple example of 6 samples. The smallest one is on the 4th position, therefore, the robot arm reverses the first 4 samples. The second smallest sample is the last one, so the next robot operation will reverse the order of five samples on positions 2–6. The third step will be to reverse the samples 3–4, etc.

Your task is to find the correct sequence of reversal operations that will sort the samples using the above algorithm. If there are more samples with the same height, their mutual order must be preserved: the one that was given first in the initial order must be placed before the others in the final order too.
 


 

Input
The input consists of several scenarios. Each scenario is described by two lines. The first line contains one integer number N , the number of samples, 1 ≤ N ≤ 100 000. The second line lists exactly N space-separated positive integers, they specify the heights of individual samples and their initial order.

The last scenario is followed by a line containing zero.
 


 

Output
For each scenario, output one line with exactly N integers P1 , P1 , . . . PN ,separated by a space.
Each Pi must be an integer (1 ≤ Pi ≤ N ) giving the position of the i-th sample just before the i-th reversal operation.

Note that if a sample is already on its correct position Pi , you should output the number Pi anyway, indicating that the “interval between Pi and Pi ” (a single sample) should be reversed.
 


 

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
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>

using namespace std;

#define MAXN 100100

int next[MAXN];
struct nodes
{
    int ch[2],f;
    int key,size,w,col;
} node[MAXN];
int pos[MAXN];

struct data
{
    int h,n;
};

void init()
{
    node[0].w=node[0].size=0;
    for(int i=0; i<MAXN-10; i++)
        next[i]=i+1;
}

int newnode(int key)
{
    int p=next[0];
    next[0]=next[p];
    node[p].key=key;
    node[p].w=1;
    node[p].col=0;
    node[p].ch[0]=node[p].ch[1]=node[p].f=0;
    return p;
}

void delnode(int p)
{
    next[p]=next[0];
    next[0]=p;
}

struct spt
{
    int root;


    void clear()
    {
        root=0;
    }

     void rotate(int x,int c)
    {
        int y=node[x].f;
        push_down(y);push_down(x);
        node[y].ch[!c]=node[x].ch[c];
        if(node[x].ch[c])
                node[node[x].ch[c]].f=y;
        node[x].f=node[y].f;
        if(node[y].f)
        {
            if(node[node[y].f].ch[0]==y)
                node[node[y].f].ch[0]=x;
            else
                node[node[y].f].ch[1]=x;
        }
        node[x].ch[c]=y;
        node[y].f=x;
        push_up(y);
        if(y==root) root=x;
    }
    void splay(int x,int f)
    {
        push_down(x);
        for(;node[x].f!=f;)
        {
            push_down(node[node[x].f].f),push_down(node[x].f),push_down(x);
            if(node[node[x].f].f==f)
            {
                if(node[node[x].f].ch[0]==x)
                    rotate(x,1);
                else
                    rotate(x,0);
            }
            else
            {
                int y=node[x].f;
                int z=node[y].f;
                if(node[z].ch[0]==y)
                {
                    if(node[y].ch[0]==x)
                        rotate(y,1),rotate(x,1);
                    else
                        rotate(x,0),rotate(x,1);
                }
                else
                {
                    if(node[y].ch[1]==x)
                        rotate(y,0),rotate(x,0);
                    else
                        rotate(x,1),rotate(x,0);
                }
            }
        }
        push_up(x);
        if(!f) root=x;
    }

    int select(int k,int rt)
    {
        int tmp,t=root;
        for(;;)
        {
            push_down(t);
            int l=node[node[t].ch[0]].size;
            if(k>l && k<=l+node[t].w) break;
            if(k<=l)
                t=node[t].ch[0];
            else
                k-=(l+node[t].w),t=node[t].ch[1];
        }
        splay(t,rt);
        return t;
    }

    void remove()
    {
        int t=root;
        if(node[t].ch[1])
        {
            root=node[root].ch[1];
            select(1,0);  //右子树第一个点旋转到根
            node[root].ch[0]=node[t].ch[0];
            if(node[t].ch[0]) node[node[t].ch[0]].f=root;
        }
        else root=node[root].ch[0];
        node[root].f=0;
        push_up(root);
        delnode(t);
    }

    void push_up(int rt)
    {
        if(!rt)return;
        int l=node[rt].ch[0];
        int r=node[rt].ch[1];
        int ret=node[rt].w;
        if(l) ret+=node[l].size;
        if(r) ret+=node[r].size;
        node[rt].size=ret;
    }

    void push_down(int rt)
    {
        if(rt && node[rt].col)
        {
            swap(node[rt].ch[0],node[rt].ch[1]);
            int l=node[rt].ch[0];
            int r=node[rt].ch[1];
            node[l].col^=1;
            node[r].col^=1;
            node[rt].col=0;
        }
    }
    int build(int l,int r,int f)
    {

        if(l>r) return 0;
        int m=(l+r)>>1;
        int p=newnode(m);
        pos[m]=p;
        node[p].f=f;
        node[p].ch[0]=build(l,m-1,p);
        node[p].ch[1]=build(m+1,r,p);
        push_up(p);
        return p;
    }

    void del(int p)
    {
        if(!p) return;
        del(node[p].ch[0]);
        del(node[p].ch[1]);
        delnode(p);
    }
};

spt s1;
int n;
data a[100010];

bool cmp(data a,data b)
{
    if(a.h==b.h)
        return a.n<b.n;
    return a.h<b.h;
}

int main()
{
    init();
    while(~scanf("%d",&n) && n)
    {
        s1.clear();
        s1.root=s1.build(1,n,0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].h);
            a[i].n=i;
        }
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            int tmp;
            s1.splay(pos[a[i].n],0);
            tmp=node[node[s1.root].ch[0]].size+i;
            node[node[s1.root].ch[0]].col^=1;
            s1.remove();
            printf("%d%s",tmp,i!=n?" ":"\n");
        }
        s1.del(s1.root);
    }
    return 0;
}


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值