• HDU 3436 Queue-jumpers (splay tree)


    Queue-jumpers

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1821    Accepted Submission(s): 425


    Problem Description
    Ponyo and Garfield are waiting outside the box-office for their favorite movie. Because queuing is so boring, that they want to play a game to kill the time. The game is called “Queue-jumpers”. Suppose that there are N people numbered from 1 to N stand in a line initially. Each time you should simulate one of the following operations:
    1.  Top x :Take person x to the front of the queue
    2.  Query x: calculate the current position of person x
    3.  Rank x: calculate the current person at position x
    Where x is in [1, N].
    Ponyo is so clever that she plays the game very well while Garfield has no idea. Garfield is now turning to you for help.
     
    Input
    In the first line there is an integer T, indicates the number of test cases.(T<=50)
    In each case, the first line contains two integers N(1<=N<=10^8), Q(1<=Q<=10^5). Then there are Q lines, each line contain an operation as said above. 
     
    Output
    For each test case, output “Case d:“ at first line where d is the case number counted from one, then for each “Query x” operation ,output the current position of person x at a line, for each “Rank x” operation, output the current person at position x at a line.
     
    Sample Input
    3 9 5 Top 1 Rank 3 Top 7 Rank 6 Rank 8 6 2 Top 4 Top 5 7 4 Top 5 Top 2 Query 1 Rank 6
     
    Sample Output
    Case 1: 3 5 8 Case 2: Case 3: 3 6
     
    Author
    wzc1989
     
    Source
     
    Recommend
    zhouzeyong
     

    离散化,

    把Top的点提取出来,其余的缩点

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013/8/25 13:28:12
      4 File Name     :F:2013ACM练习专题学习splay_tree_2HDU3436.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 
     21 #define Key_value ch[ch[root][1]][0]
     22 const int MAXN = 200010;
     23 int pre[MAXN],ch[MAXN][2],size[MAXN];
     24 int num[MAXN];//r结点包含的数的个数
     25 int s[MAXN],e[MAXN];
     26 int cnt;//离散分段后的个数
     27 int root,tot1;
     28 
     29 //debug部分**********************************
     30 void Treavel(int x)
     31 {
     32     if(x)
     33     {
     34         Treavel(ch[x][0]);
     35         printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d  num = %2d s = %2d e = %2d
    ",x,ch[x][0],ch[x][1],pre[x],size[x],num[x],s[x],e[x]);
     36         Treavel(ch[x][1]);
     37     }
     38 }
     39 void debug()
     40 {
     41     printf("root:%d
    ",root);
     42     Treavel(root);
     43 }
     44 //以上是debug部分**************************************
     45 
     46 
     47 
     48 void NewNode(int &r,int father,int k)
     49 {
     50     r = k;
     51     ch[r][0] = ch[r][1] = 0;
     52     size[r] = e[k] - s[k] + 1;
     53     num[r] = e[k] - s[k] + 1;
     54     pre[r] = father;
     55 }
     56 void push_up(int r)
     57 {
     58     size[r] = size[ch[r][0]] + size[ch[r][1]] + num[r];
     59 }
     60 void push_down(int r)
     61 {
     62     
     63 }
     64 void Build(int &x,int l,int r,int father)
     65 {
     66     if(l > r)return;
     67     int mid = (l+r)/2;
     68     NewNode(x,father,mid);
     69     Build(ch[x][0],l,mid-1,x);
     70     Build(ch[x][1],mid+1,r,x);
     71     push_up(x);
     72 }
     73 void Init()
     74 {
     75     root = tot1 = 0;
     76     ch[root][0] = ch[root][1] = num[root] = size[root] = pre[root] = 0;
     77     Build(root,1,cnt,0);
     78     push_up(root);
     79 }
     80 //旋转,0为左旋,1为右旋
     81 void Rotate(int x,int kind)
     82 {
     83     int y = pre[x];
     84     push_down(y);
     85     push_down(x);//先把y的标记下传,在把x的标记下传
     86     ch[y][!kind] = ch[x][kind];
     87     pre[ch[x][kind]] = y;
     88     if(pre[y])
     89         ch[pre[y]][ch[pre[y]][1]==y] = x;
     90     pre[x] = pre[y];
     91     ch[x][kind] = y;
     92     pre[y] = x;
     93     push_up(y);
     94 }
     95 //Splay调整,将r结点调整到goal下面
     96 void Splay(int r,int goal)
     97 {
     98     push_down(r);
     99     while(pre[r] != goal)
    100     {
    101         if(pre[pre[r]] == goal)
    102             Rotate(r,ch[pre[r]][0]==r);
    103         else
    104         {
    105             int y = pre[r];
    106             int kind = ch[pre[y]][0]==y;
    107             if(ch[y][kind] == r)
    108             {
    109                 Rotate(r,!kind);
    110                 Rotate(r,kind);
    111             }
    112             else
    113             {
    114                 Rotate(y,kind);
    115                 Rotate(r,kind);
    116             }
    117         }
    118     }
    119     push_up(r);
    120     if(goal == 0) root = r;
    121 }
    122 
    123 
    124 int Get_Min(int r)
    125 {
    126     push_down(r);
    127     while(ch[r][0])
    128     {
    129         r = ch[r][0];
    130         push_down(r);
    131     }
    132     return r;
    133 }
    134 int Get_Max(int r)
    135 {
    136     push_down(r);
    137     while(ch[r][1])
    138     {
    139         r = ch[r][1];
    140         push_down(r);
    141     }
    142     return r;
    143 }
    144 //删除根结点
    145 void Delete()
    146 {
    147     if(ch[root][0] == 0 || ch[root][1] == 0)
    148     {
    149         root = ch[root][0] + ch[root][1];
    150         pre[root] = 0;
    151         return;
    152     }
    153     int k = Get_Min(ch[root][1]);
    154     Splay(k,root);
    155     Key_value = ch[root][0];
    156     root = ch[root][1];
    157     pre[ch[root][0]] = root;
    158     pre[root] = 0;
    159     push_up(root);
    160 }
    161 
    162 int Bin(int x)//二分查找x属于哪一段
    163 {
    164     int l = 1, r = cnt;
    165     while(l <= r)
    166     {
    167         int mid = (l+r)/2;
    168         if(s[mid] <= x && x <= e[mid])return mid;
    169         if(x < s[mid])r = mid-1;
    170         else l = mid+1;
    171     }
    172     return -1;
    173 }
    174 
    175 //将点x放到最前面
    176 void Top(int x)
    177 {
    178     int r = Bin(x);
    179     Splay(r,0);
    180     Delete();
    181     Splay(Get_Min(root),0);
    182     ch[r][0] = 0;
    183     ch[r][1] = root;
    184     pre[root] = r;
    185     root = r;
    186     pre[root] = 0;
    187     push_up(root);
    188 }
    189 int Query(int x)
    190 {
    191     int r = Bin(x);
    192     Splay(r,0);
    193     return size[ch[root][0]] + x - s[r] + 1;
    194 }
    195 int Get_Rank(int r,int k)
    196 {
    197     int t  = size[ch[r][0]];
    198     if(k <= t)return Get_Rank(ch[r][0],k);
    199     else if(k <= t + num[r]) return s[r] + k - t - 1;
    200     else return Get_Rank(ch[r][1],k - t - num[r]);
    201 }
    202 char op[MAXN][10];
    203 int qnum[MAXN];
    204 int p[MAXN];
    205 
    206 int main()
    207 {
    208     //freopen("in.txt","r",stdin);
    209     //freopen("out.txt","w",stdout);
    210      int N,Q;
    211     int T;    
    212     scanf("%d",&T);
    213     int iCase = 0;
    214     while(T--)
    215     {
    216         iCase++;
    217         scanf("%d%d",&N,&Q);
    218         int t = 0;
    219         for(int i = 0;i < Q;i++)
    220         {
    221             scanf("%s%d",&op[i],&qnum[i]);
    222             if(op[i][0] == 'T')
    223                 p[t++] = qnum[i];
    224         }
    225         p[t++] = 1;
    226         p[t++] = N;
    227         sort(p,p+t);
    228         t = unique(p,p+t) - p;
    229         cnt = 0;
    230         for(int i = 0;i < t;i++)
    231         {
    232             if(i > 0 && p[i] - p[i-1] > 1)
    233             {
    234                 cnt++;
    235                 s[cnt] = p[i-1] + 1;
    236                 e[cnt] = p[i] - 1;
    237             }
    238             cnt++;
    239             s[cnt] = p[i];
    240             e[cnt] = p[i];
    241         }
    242         Init();
    243     //    debug();
    244         //continue;
    245         printf("Case %d:
    ",iCase);
    246         for(int i = 0;i < Q;i++)
    247         {
    248             if(op[i][0] == 'T')Top(qnum[i]);
    249             else if(op[i][0] =='Q')printf("%d
    ",Query(qnum[i]));
    250             else printf("%d
    ",Get_Rank(root,qnum[i]));
    251             //debug();
    252         }
    253     }
    254     return 0;
    255 }
  • 相关阅读:
    面试题|Docker的优缺点
    【华为出品】物联网全栈开发实战营来啦!送海思双目开发板
    Nginx实战|Nginx健康检查
    Linux中几个正则表达式的用法
    盘点提高国内访问 Github 的速度的 9 种方案
    一行代码如何隐藏 Linux 进程?
    (二)类加载机制与反射:类加载器
    (一)类加载机制与反射:类的加载,连接和初始化
    (八)多线程:线程相关类
    (七)多线程:线程池
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3281590.html
Copyright © 2020-2023  润新知