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
2010 ACM-ICPC Multi-University Training Contest(1)——Host by FZU  

 

Recommend zhouzeyong  

 

 

离散化,

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

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013/8/25 13:28:12
  4 File Name     :F:\2013ACM练习\专题学习\splay_tree_2\HDU3436.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\n",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\n",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:\n",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\n",Query(qnum[i]));
250             else printf("%d\n",Get_Rank(root,qnum[i]));
251             //debug();
252         }
253     }
254     return 0;
255 }

 

 

 

 

 

 

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/p/3281590.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞