Splay练习题 [HDU 1890] Robotic Sort

Robotic Sort

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

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

Source

2008 “Shun Yu Cup” Zhejiang Collegiate Programming Contest - Warm Up(2)

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100100

struct node
{
    int pos,val;
}num[N];

int mp[N];
int val[N];
int reflect[N];

bool cmp(node a,node b)
{
    if(a.val!=b.val)
        return a.val<b.val;
    return a.pos<b.pos;
}

struct SplayTree
{
    int ch[N][2],pre[N],size[N],lazy[N];
    int root,top;

    void PushUp(int x)
    {
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    }

    void PushDown(int x)
    {
        if(lazy[x])
        {
            swap(ch[x][0],ch[x][1]);
            lazy[ch[x][0]]^=1;
            lazy[ch[x][1]]^=1;
            lazy[x]=0;
        }
    }

    void Rotate(int x,int c)
    {
        int y=pre[x];
        PushDown(y);
        PushDown(x);
        ch[y][!c]=ch[x][c];
        if(ch[x][c]) pre[ch[x][c]]=y;
        pre[x]=pre[y];
        if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        ch[x][c]=y;
        pre[y]=x;
        PushUp(y);
    }

    void Splay(int x,int f)
    {
        PushDown(x);
        while(pre[x]!=f)
        {
            PushDown(pre[pre[x]]);
            PushDown(pre[x]);
            PushDown(x);
            if(pre[pre[x]]==f) Rotate(x,ch[pre[x]][0]==x);
            else
            {
                int y=pre[x];
                int z=pre[y];
                int c=(ch[z][0]==y);
                if(ch[y][c]==x)
                {
                    Rotate(x,!c);
                    Rotate(x,c);
                }
                else
                {
                    Rotate(y,c);
                    Rotate(x,c);
                }
            }
        }
        PushUp(x);
        if(f==0) root=x;
    }

    void Splay_Kth(int k,int f)
    {
        int x=root;
        PushDown(x);
        while(1)
        {
            if(k==size[ch[x][0]]+1) break;
            else if(k<size[ch[x][0]]+1) x=ch[x][0];
            else
            {
                k-=size[ch[x][0]]+1;
                x=ch[x][1];
            }
            PushDown(x);
        }
        Splay(x,f);
    }

    void Newnode(int &x)
    {
        x=++top;
        ch[x][0]=ch[x][1]=pre[x]=lazy[x]=0;
        size[x]=1;
    }

    void Build(int &x,int l,int r,int f)
    {
        if(l>r) return;
        int m=(l+r)>>1;
        Newnode(x);
        val[x]=num[reflect[m]].val;
        mp[reflect[m]]=x;               //建立映射
        Build(ch[x][0],l,m-1,x);
        Build(ch[x][1],m+1,r,x);
        pre[x]=f;
        PushUp(x);
    }

    void Init(int n)
    {
        top=root=0;
        ch[0][0]=ch[0][1]=size[0]=pre[0]=lazy[0]=val[0]=0;
        Build(root,1,n,0);
    }

    void Del()
    {
        int t=root;
        if(ch[root][1])
        {
            root=ch[root][1];
            Splay_Kth(1,0);
            ch[root][0]=ch[t][0];
            if(ch[root][0]) pre[ch[root][0]]=root;
        }
        else root=ch[root][0];
        pre[root]=0;
        PushUp(root);
    }
}t;

int main()
{
    int n,i;
    while(scanf("%d",&n) && n)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&num[i].val);
            num[i].pos=i;
        }
        sort(num+1,num+n+1,cmp);
        for(i=1;i<=n;i++)
        {
            reflect[num[i].pos]=i;
        }
        t.Init(n);
        for(i=1;i<=n;i++)
        {
            t.Splay(mp[i],0);
            int ans=i+t.size[t.ch[t.root][0]];
            t.lazy[t.ch[t.root][0]]^=1;
            t.Del();
            if(i!=1) printf(" ");
            printf("%d",ans);
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-11-06 09:46:41

Splay练习题 [HDU 1890] Robotic Sort的相关文章

hdu 1890 Robotic Sort(splay 区间反转+删点)

题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的splay区间翻转+删点. 我们把数据排序,然后记录一下每个数原来的位置,然后splay建树的时候用原来的位置来对应,这样val[i].second就直接是这个数在splay中的那个节点. (当然你也可以普通建树,然后手动记录位置). 然后我们把要找的那个数对应的节点旋转到根,然后根左边的size+i就

HDU 1890 Robotic Sort

题意: 将一列数字排序  排序规则是  每次找到最小值的位置loc  将1~loc所有数字颠倒  然后删掉第一位  直到排好序  排序要求是稳定的 思路: 这题要做的是  寻找区间最小值位置  翻转区间  的操作  因此可以想到用splay 只需要每个节点记录一个small  就可以实现找到最小值位置 翻转区间操作就是将splay的超级头转到最上面使之成为根  再把loc转到根下面  这时根的右儿子的左儿子就是需要翻转的区间  用一个rev延迟更新  然后将loc转到最上面是指成为根  删掉根

HDU 1890 Robotic Sort 伸展树的区间反转与延迟标记

延迟标记像极了线段树,不再多说. 区间反转在树伸展到位之后,也变成了简单的递归交换左右儿子. 愈发感觉到伸展树简直太漂亮了,伸展操作更是诱惑到不行 ,总之数据结构太有魅力了. 比较简单,就直接上模板了. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #in

数据结构(Splay平衡树):HDU 1890 Robotic Sort

Robotic Sort Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3456    Accepted Submission(s): 1493 Problem Description Somewhere deep in the Czech Technical University buildings, there are labora

HDU 1890 Robotic Sort(splay)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i的所在位置.相等的两个数排序后相对位置不变. [思路] 由于相对位置不变,所以可以根据数值与位置重编号. 依旧使用直接定位从上到下旋转至根的splay写法.每次将i结点旋转至根,则答案为左儿子大小+i,然后将i删掉合并左右儿子. 需要注意合并时判断左右儿子是否为空,以及各种pushdown下传标记.

HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratories for examining

HDU 1890 Robotic Sort (Splay)

题意:将一列数字排序  排序规则是  每次找到最小值的位置loc  将1~loc所有数字颠倒  然后删掉第一位  直到排好序  排序要求是稳定的. 析:直接用splay来维护最小值,然后插入删除即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include

HDU 1890 Robotie Sort

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 labo

HDU 1890 Splay区间翻转

D - Robotic Sort Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 1890 Appoint description:  System Crawler  (2014-11-27) Description Somewhere deep in the Czech Technical University buildings, t