(转)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 }
原文地址:https://www.cnblogs.com/violet-acmer/p/9388832.html