• [BZOJ1552] [Cerc2007] robotic sort (splay)


    Description

    Input

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

    Output

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

    Sample Input

    6
    3 4 5 1 6 2

    Sample Output

    4 6 4 5 6 6

    HINT 

    Source

      HNOI2009集训Day6

    Solution

      预处理$[1, n]$中所有数的位置,每次把当前查找的数$x$旋到根上,其左儿子的子树大小就是答案。再对题意所述的区间加个reverse标记即可。

      因为有区间加标记,所以最好加上头尾两个虚拟节点。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct spaly
     4 {
     5     int c[2], fa, siz, rev;
     6 }a[100005];
     7 pair<int, int> b[100005];
     8  
     9 void push_up(int k)
    10 {
    11     a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1;
    12 }
    13  
    14 void push_down(int k)
    15 {
    16     if(a[k].rev)
    17     {
    18         swap(a[k].c[0], a[k].c[1]), a[k].rev = 0;
    19         a[a[k].c[0]].rev ^= 1, a[a[k].c[1]].rev ^= 1;
    20     }
    21 }
    22  
    23 void rotate(int &k, int x)
    24 {
    25     int y = a[x].fa, z = a[y].fa;
    26     int dy = a[y].c[1] == x, dz = a[z].c[1] == y;
    27     if(k == y) k = x, a[x].fa = z;
    28     else a[z].c[dz] = x, a[x].fa = z;
    29     a[y].c[dy] = a[x].c[!dy], a[a[x].c[!dy]].fa = y;
    30     a[x].c[!dy] = y, a[y].fa = x;
    31     push_up(y);
    32 }
    33  
    34 void splay(int &k, int x)
    35 {
    36     while(k != x)
    37     {
    38         int y = a[x].fa, z = a[y].fa;
    39         push_down(z), push_down(y), push_down(x);
    40         if(k != y)
    41             if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x);
    42             else rotate(k, y);
    43         rotate(k, x);
    44     }
    45     push_up(x);
    46 }
    47  
    48 int find(int k, int x)
    49 {
    50     if(!k) return 0;
    51     push_down(k);
    52     if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x);
    53     if(x == a[a[k].c[0]].siz + 1) return k;
    54     return find(a[k].c[1], x - a[a[k].c[0]].siz - 1);
    55 }
    56  
    57 int main()
    58 {
    59     int n, root, pos;
    60     while(~scanf("%d", &n) && n)
    61     {
    62         for(int i = 1; i <= n; i++)
    63         {
    64             scanf("%d", &b[i].first);
    65             b[i].second = i + 1;
    66         }
    67         sort(b + 1, b + n + 1);
    68         for(int i = 1; i <= n + 2; i++)
    69         {
    70             a[i].fa = i + 1, a[i].c[0] = i - 1;
    71             a[i].siz = i, a[i].c[1] = a[i].rev = 0;
    72         }
    73         a[n + 2].fa = 0, root = n + 2;
    74         for(int i = 1; i <= n; i++)
    75         {
    76             splay(root, b[i].second);
    77             pos = a[a[root].c[0]].siz;
    78             printf("%d", pos);
    79             if(i != n) printf(" ");
    80             splay(root, find(root, i));
    81             splay(a[root].c[1], find(root, pos + 2));
    82             a[a[a[root].c[1]].c[0]].rev ^= 1;
    83         }
    84         puts("");
    85     }
    86     return 0;
    87 }
    View Code

       双倍经验的时候到了(。・ω・)ノ゙BZOJ3506 我是雷锋我骄傲。

  • 相关阅读:
    .NET中使用嵌入的资源
    C#操作注册表
    .Net中大数加减乘除运算
    CYQ.Data 轻量数据层之路 V4.5 版本发布[更好的使用体验,更优的缓存机制]
    关于性能比较的应用误区
    秋色园QBlog技术原理解析:性能优化篇:打印页面SQL,全局的SQL语句优化(十三)
    CYQ.DBImport 数据库反向工程及批量导数据库工具 V1.0 发布
    框架设计之菜鸟漫漫江湖路系列 一:菜鸟入门
    MySql折腾小记二:text/blog类型不允许设置默认值,不允许存在两个CURRENT_TIMESTAMP
    CYQ.Data.Xml XmlHelper 助你更方便快捷的操作Xml/Html
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5415703.html
Copyright © 2020-2023  润新知