zoukankan      html  css  js  c++  java
  • 【bzoj1552】[Cerc2007]robotic sort Splay

    题目描述

    输入

    输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

    输出

    输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

    样例输入

    6
    3 4 5 1 6 2

    样例输出

    4 6 4 5 6 6


    题解

    splay

    先将原数据从小到大排序,类似于离散化,把它们的排名存入splay中。

    那么第k小的数的数组下标就是k。

    区间反转即可。

    #include <cstdio>
    #include <algorithm>
    #define N 100005
    using namespace std;
    struct data
    {
        int num , pos;
    }a[N];
    int c[2][N] , fa[N] , tag[N] , si[N] , id[N] , root;
    bool cmp(data a , data b)
    {
        return a.num == b.num ? a.pos < b.pos : a.num < b.num;
    }
    void pushup(int k)
    {
        si[k] = si[c[0][k]] + si[c[1][k]] + 1;
    }
    void pushdown(int k)
    {
        if(tag[k])
        {
            swap(c[0][c[0][k]] , c[1][c[0][k]]);
            swap(c[0][c[1][k]] , c[1][c[1][k]]);
            tag[c[0][k]] ^= 1;
            tag[c[1][k]] ^= 1;
            tag[k] = 0;
        }
    }
    void build(int l , int r , int f)
    {
        if(l > r) return;
        int mid = (l + r) >> 1;
        build(l , mid - 1 , mid);
        build(mid + 1 , r , mid);
        fa[id[mid]] = id[f];
        c[mid > f][id[f]] = id[mid];
        pushup(id[mid]);
    }
    void rotate(int &k , int x)
    {
        int y = fa[x] , z = fa[y] , l , r;
        l = (c[0][y] != x);
        r = l ^ 1;
        if(y == k) k = x;
        else if(c[0][z] == y) c[0][z] = x;
        else c[1][z] = x;
        fa[x] = z;
        fa[y] = x;
        fa[c[r][x]] = y;
        c[l][y] = c[r][x];
        c[r][x] = y;
        pushup(y);
        pushup(x);
    }
    void splay(int &k , int x)
    {
        while(x != k)
        {
            int y = fa[x] , z = fa[y];
            if(y != k)
            {
                if(c[0][y] == x ^ c[0][z] == y) rotate(k , x);
                else rotate(k , y);
            }
            rotate(k , x);
        }
    }
    int getrank(int x)
    {
        if(x == root) return si[c[0][x]] + 1;
        int r = getrank(fa[x]);
        pushdown(x);
        if(x == c[0][fa[x]]) r -= si[c[1][x]] + 1;
        else r += si[c[0][x]] + 1;
        return r;
    }
    int find(int k , int x)
    {
        pushdown(k);
        if(x <= si[c[0][k]]) return find(c[0][k] , x);
        else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
        else return k;
    }
    int main()
    {
        int n , i;
        scanf("%d" , &n);
        for(i = 1 ; i <= n ; i ++ )
        {
            scanf("%d" , &a[i].num);
            a[i].pos = i;
        }
        sort(a + 1 , a + n + 1 , cmp);
        for(i = 1 ; i <= n ; i ++ )
            id[a[i].pos + 1] = i;
        id[1] = n + 1;
        id[n + 2] = n + 2;
        build(1 , n + 2 , 0);
        root = id[(n + 3) >> 1];
        for(i = 1 ; i <= n ; i ++ )
        {
            int ri = getrank(i) , tx , ty;
            printf("%d%c" , ri - 1 , i == n ? '
    ' : ' ');
            tx = find(root , i);
            ty = find(root , ri + 1);
            splay(root , tx);
            splay(c[1][root] , ty);
            swap(c[0][c[0][c[1][root]]] , c[1][c[0][c[1][root]]]);
            tag[c[0][c[1][root]]] ^= 1;
        }
        return 0;
    }
  • 相关阅读:
    [转]Magento刷新索引的几种方法
    [转]centos7 移动mysql5.7.19 数据存储位置
    [转]解决Magento批量导入带图片的商品的问题
    [转]【mysql监控】查看mysql库大小,表大小,索引大小
    [转]Centos系统中查看文件和文件夹大小
    [转]Magento 2.2 Developer Documentation
    [转]Magento2开发教程
    [转]Magento Configurable Product
    [转]论magento1和magento2的速度性能优化问题
    [转]本地 Windows 计算机密码登录 登录 腾讯云 Linux 实例
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6289860.html
Copyright © 2011-2022 走看看