zoukankan      html  css  js  c++  java
  • (转)hdu 3436Queue-jumpers--splay+离散化

    dalao博客

    http://acm.hdu.edu.cn/showproblem.php?pid=3436

    题意:初始排列1到N,现在要你实现3种操作:

    将x插入到队头去

    询问x当前的位置

    询问第x个位置上当前是谁.

    分析:

    下面用SplayTree来实现.不过依然要明白SplayTree提供的是N个房间,第i号房间里放的就是第i个人,各种操作不会变化房间的内容,变得只是房间之间的相对父子关系而已.

    SplayTree需要 size,pre,ch 3种信息即可.

    首先将1到n建立SPlayTree.

    我们将根root节点的右儿子的左儿子位置称为关键位置.

    对于top x操作:由于第x个人在x号房间里,先将x号房间旋转到根,删除根,在将最小的节点旋转到根,然后用x号房间替换最小的节点称为根.

    对于Query x操作:直接将x+1号房间转到根节点,返回它左子树儿子个数即可.

    对于Rank x 操作:直接用Get_Kth即可实现,找到第x+1位置的房间号.

    不过这道题的N<=10^8,但是Q<=10^5,所以需要将数据离散化,对于所有top x命令,我们将所有区间离散化,然后依然第i个房间放的是顺序第i个区间,SplayTree的size数组表示节点r为根的树中所有区间包含的整数个数,num数组表示节点r(仅仅r节点)表示的区间所包含的数总数,也就是顺序第r个区间包含的数的总数.

    AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int maxn=200000+100;
      7 int N,Q,T;
      8 int s[maxn],e[maxn],cnt;//表示区间
      9 int p[maxn];//提取出来的单点数
     10 char op[maxn][10];//命令
     11 int qnum[maxn];//命令参数
     12 int bin(int x)
     13 {
     14     int l=1,r=cnt;
     15     while(l<=r)
     16     {
     17         int mid=(l+r)>>1;
     18         if(s[mid]<=x && x<=e[mid])
     19             return mid;
     20         else if(x< s[mid])
     21             r=mid-1;
     22         else
     23             l=mid+1;
     24     }
     25     return -1;
     26 }
     27 
     28 int size[maxn];
     29 int num[maxn];
     30 int pre[maxn];
     31 int ch[maxn][2],root;
     32 
     33 void Treavel(int x)
     34 {
     35     if(x)
     36     {
     37         Treavel(ch[x][0]);
     38 
     39         printf("节点 %2d: 左儿子 %2d 右儿子 %2d ",x,ch[x][0],ch[x][1]);
     40         printf("size %2d num %2d pre %2d s %2d e %2d
    ",size[x],num[x],pre[x],s[x],e[x]);
     41 
     42         Treavel(ch[x][1]);
     43     }
     44 }
     45 void DeBug()
     46 {
     47     printf("root:%d
    ",root);
     48     Treavel(root);
     49 }
     50 void Push_Up(int r)
     51 {
     52     size[r] = size[ch[r][0]]+size[ch[r][1]]+num[r];
     53 }
     54 void Rotate(int x,int kind)
     55 {
     56     int y=pre[x];
     57     ch[y][kind^1] = ch[x][kind];
     58     pre[ch[x][kind]] = y;
     59     if(pre[y])
     60         ch[pre[y]][ch[pre[y]][1] == y] = x;
     61     pre[x]=pre[y];
     62     ch[x][kind]=y;
     63     pre[y]=x;
     64     Push_Up(y);
     65 }
     66 
     67 void Splay(int r,int goal)
     68 {
     69     while(pre[r]!=goal)
     70     {
     71         if(pre[pre[r]]==goal)
     72             Rotate(r,ch[pre[r]][0]==r);
     73         else
     74         {
     75             int y=pre[r];
     76             int kind=ch[pre[y]][0] == y;
     77             if(ch[y][kind] == r)
     78             {
     79                 Rotate(r,kind^1);
     80                 Rotate(r,kind);
     81             }
     82             else
     83             {
     84                 Rotate(y,kind);
     85                 Rotate(r,kind);
     86             }
     87         }
     88     }
     89     Push_Up(r);
     90     if(goal==0)
     91         root=r;
     92 }
     93 void New_Node(int &r,int fa,int k)
     94 {
     95     r=k;
     96     num[r]=size[r]=e[k]-s[k]+1;
     97     pre[r]=fa;
     98     ch[r][0]=ch[r][1]=0;
     99 }
    100 void Build(int &x,int l,int r,int fa)
    101 {
    102     if(l>r)
    103         return;
    104     int mid=(l+r)>>1;
    105     New_Node(x,fa,mid);
    106     Build(ch[x][0],l,mid-1,x);
    107     Build(ch[x][1],mid+1,r,x);
    108     Push_Up(x);
    109 }
    110 void init()
    111 {
    112     root=0;
    113     pre[root]=0;
    114     ch[root][0]=ch[root][1]=0;
    115     size[root]=0;
    116     num[root]=0;
    117     Build(root,1,cnt,0);
    118 }
    119 int Get_Min(int r)
    120 {
    121     while(ch[r][0]) r=ch[r][0];
    122     return r;
    123 }
    124 
    125 //删除树根
    126 void Delete()
    127 {
    128     if(ch[root][0]==0 || ch[root][1]==0)
    129     {
    130         root = ch[root][0]+ch[root][1];
    131         pre[root]=0;
    132         return ;
    133     }
    134     int k=Get_Min(ch[root][1]);
    135     Splay(k,root);
    136     ch[k][0]=ch[root][0];
    137     pre[ch[root][0]]=k;
    138     root=k;
    139     pre[k]=0;
    140     Push_Up(root);
    141 }
    142 void Top(int x)
    143 {
    144     int r=bin(x);
    145     Splay(r,0);
    146     Delete();
    147     Splay(Get_Min(root),0);
    148     ch[r][0]=0;
    149     ch[r][1]=root;
    150     pre[r]=0;
    151     pre[root]=r;
    152     root=r;
    153     Push_Up(r);
    154 }
    155 int Query(int x)
    156 {
    157     int r=bin(x);
    158     Splay(r,0);
    159     return size[ch[r][0]]+x-s[r]+1;
    160 }
    161 int Rank(int x)
    162 {
    163     int r=root;
    164     while(1)
    165     {
    166         //size[r]我之前写成了N,一直WA
    167         if(size[ch[r][0]] < x && size[r]-size[ch[r][1]] >= x)
    168             return s[r]-1+x-size[ch[r][0]];
    169         else if(x<=size[ch[r][0]])
    170             r=ch[r][0];
    171         else
    172         {
    173             //这里的顺序千万别写反了,而且size[r]我之前写成了N,一直WA
    174             x-=size[r]-size[ch[r][1]];
    175             r=ch[r][1];
    176         }
    177     }
    178 }
    179 
    180 //和上面那个Rank函数一样的功能,两个二选一,用一个即可
    181 int Get_Rank(int r,int k)
    182 {
    183     int t = size[ch[r][0]];
    184     if(k <= t)
    185         return Get_Rank(ch[r][0],k);
    186     else if(k <= t + num[r])
    187         return s[r] + k - t - 1;
    188     else
    189         return Get_Rank(ch[r][1],k-t-num[r]);
    190 }
    191 
    192 int main()
    193 {
    194     scanf("%d",&T);
    195     for(int kase=1;kase<=T;kase++)
    196     {
    197         scanf("%d%d",&N,&Q);
    198 
    199         int t=0;
    200         for(int i=1;i<=Q;i++)
    201         {
    202             scanf("%s%d",op[i],&qnum[i]);
    203             if(op[i][0]=='T')
    204                 p[t++]=qnum[i];
    205         }
    206         p[t++]=1;
    207         p[t++]=N;
    208         sort(p,p+t);
    209         t=unique(p,p+t)-p;
    210         cnt=0;
    211         for(int i=0;i<t;i++)
    212         {
    213             if(i>0 && p[i]>p[i-1]+1)
    214             {
    215                 cnt++;
    216                 s[cnt]=p[i-1]+1;
    217                 e[cnt]=p[i]-1;
    218             }
    219             cnt++;
    220             s[cnt]=e[cnt]=p[i];
    221         }
    222         init();
    223         printf("Case %d:
    ",kase);
    224         for(int i=1;i<=Q;i++)
    225         {
    226             if(i==4)
    227             {
    228                 int x=1;
    229                 int y=1;
    230             }
    231             if(op[i][0]=='T')
    232                 Top(qnum[i]);
    233             else if(op[i][0]=='Q')
    234                 printf("%d
    ",Query(qnum[i]));
    235             else if(op[i][0]=='R')
    236                 printf("%d
    ",Rank(qnum[i]));
    237         }
    238     }
    239     return 0;
    240 }
  • 相关阅读:
    Phpstudy升级到Mysql8
    PHP 匿名函数使用技巧
    PHP 中的CURL 模拟表单的post提交
    Go中局部全局变量的区分
    Php中的goto用法
    struct的匿名用法详解
    Go中多个返回值的技巧
    C# 多线程之List的线程安全问题
    C# 多线程七之Parallel
    C# 多线程六之Task(任务)三之任务工厂
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9388832.html
Copyright © 2011-2022 走看看