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

延迟标记像极了线段树,不再多说。

区间反转在树伸展到位之后,也变成了简单的递归交换左右儿子。

愈发感觉到伸展树简直太漂亮了,伸展操作更是诱惑到不行 ,总之数据结构太有魅力了。

比较简单,就直接上模板了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 9999991

using namespace std;

const int MAXN = 100100;

struct N
{
    //info
    int son[2],pre,data;

    //data
    bool mark;
    int ls,rs,s;
} st[MAXN];

int Top;

struct W
{
    int data,site;
} num[MAXN],tnum[MAXN];

bool cmp(W a1,W a2)
{
    if(a1.data < a2.data)
        return true;
    if(a1.data == a2.data && a1.site < a2.site)
        return true;
    return false;
}

void Push_Down(int root)
{
    if(st[root].mark == 1)
    {
        st[root].mark = 0;
        if(st[root].son[0] != -1)
            st[st[root].son[0]].mark ^= 1;
        if(st[root].son[1] != -1)
            st[st[root].son[1]].mark ^= 1;

        int temp;
        temp = st[root].son[0];
        st[root].son[0] = st[root].son[1];
        st[root].son[1] = temp;

        temp = st[root].ls;
        st[root].ls = st[root].rs;
        st[root].rs = temp;
    }
}

void Updata(int root)
{
    st[root].ls = st[root].son[0] == -1 ? 0 : st[st[root].son[0]].s;
    st[root].rs = st[root].son[1] == -1 ? 0 : st[st[root].son[1]].s;
    st[root].s = st[root].ls + st[root].rs + 1;
}

void Init(int &root,int s,int e,int pre)
{
    if(s > e)
        return ;
    int mid = (s+e)>>1;

    root = Top++;
    st[root].son[0] = -1;
    st[root].son[1] = -1;
    st[root].pre = pre;
    st[root].data = num[mid].data;
    st[root].mark = 0;
    num[mid].site = root;

    Init(st[root].son[0],s,mid-1,root);
    Init(st[root].son[1],mid+1,e,root);

    Updata(root);
}

void Rotate(int root,int dir)
{
    st[st[root].pre].son[dir] = st[root].son[1^dir];
    st[root].son[1^dir] = st[root].pre;

    if(st[st[st[root].pre].pre].son[0] == st[root].pre)
        st[st[st[root].pre].pre].son[0] = root;
    else
        st[st[st[root].pre].pre].son[1] = root;
    int temp = st[root].pre;
    st[root].pre = st[st[root].pre].pre;
    st[temp].pre = root;

    if(st[temp].son[dir] != -1)
        st[st[temp].son[dir]].pre = temp;
    Updata(temp);
    Updata(root);
}

void Updata_Lazy(int root,int goal)
{
    if(st[root].pre != goal)
    {
        Updata_Lazy(st[root].pre,goal);
    }

    Push_Down(root);
}

int Splay(int root,int goal)
{
    Updata_Lazy(root,goal);

    while(st[root].pre != goal)
    {
        Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1));
    }

    return root;
}

int Search_Site(int root,int site)
{
    do
    {
        Push_Down(root);

        if(st[root].ls + 1 == site)
            return root;
        if(st[root].ls + 1 < site)
        {
            site = site - st[root].ls - 1;
            root = st[root].son[1];
        }
        else
            root = st[root].son[0];
    }while(1);
}

int main()
{
    int n;

    int i;

    int root,lsite,rsite;

    while(scanf("%d",&n) && n)
    {
        for(i = 2; i <= n+1; ++i)
        {
            scanf("%d",&tnum[i].data);
            num[i].site = i;
            tnum[i].site = i;
        }

        sort(tnum+2,tnum+n+2,cmp);

        num[1].data = 1,num[1].site = 1;
        num[n+2].data = n+2,num[n+2].site = n+2;

        for(i = 2; i <= n+1; ++i)
        {
            num[tnum[i].site].data = i;
        }

        root = -1,Top = 1;

        Init(root,1,n+2,0);

        st[0].son[0] = root,st[0].son[1] = -1;//虚拟父节点

        for(i = 2; i <= n+1; ++i)
        {
            root = Splay(num[tnum[i].site].site,0);

            printf("%d",st[root].ls);
            if(i == n+1) printf("\n");
            else printf(" ");

            lsite = min(st[root].ls+1,num[tnum[i].site].data)-1;
            rsite = max(st[root].ls+1,num[tnum[i].site].data)+1;
            lsite = Search_Site(root,lsite);
            rsite = Search_Site(root,rsite);
            root = Splay(rsite,0);
            root = Splay(lsite,0);
            st[st[st[root].son[1]].son[0]].mark ^= 1;
        }

    }
    return 0;
}

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

时间: 2024-10-13 07:08:44

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 - [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

数据结构(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

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 labor

hdu1890 伸展树(区间反转)

对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交换左右 子树就可以了(中序),根结点的位置就是i+siz[ch[root][0]],i是处理完的结点个数,siz[ch[root][0]]就是左子树(需要旋转的个数). 旋转可以用lazy思想标记,这样时间就为logn了.由于第k大的值已经处理完成,所以直接将根结点删除. 代码: #include<

线段树 (区间修改 区间查询 延迟标记)

hdu 1698 Just a Hook 题意: 给你一链子,这天链子由金银铜三种钩子组成,每种钩子都有自己的价值,起初,这条钩子全部由铜钩子组成,给你两个数n(钩子的个数),Q(操作的个数)每次操作就是将给定区间里的数变成某种钩子,求这条链子的总价值. 分析: 线段树模版题,处理好延迟标记即可. 代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #in

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)

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