hdu3436 Queue-jumpers(Splay)
来源:互联网 发布:js接口安全域名 备案 编辑:程序博客网 时间:2024/05/29 16:10
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3411 Accepted Submission(s): 923
Total Submission(s): 3411 Accepted Submission(s): 923
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.
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.
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
39 5Top 1Rank 3Top 7Rank 6Rank 86 2Top 4Top 57 4Top 5Top 2Query 1Rank 6
Sample Output
Case 1:358Case 2:Case 3:36题意:给你一个长为n的序列,第i个数的编号是i,有3个操作,1:把编号为x的数放到序列最前面;2:询问编号为x的数的位置;3:询问第x个位置上的数的编号。
思路:因为n很大(1e8)所以要先离散化,我们把询问的数字都保存下来,变为一个号数的区间 ,然后其他区间都缩成一个点,那么区间的长度最大就为2*10^5了。然后我们先按照位置建立splay,接着就是是play的经典操作了。
下面写了两种程序,第一种是每次找到编号x的数对应的节点,然后再算,第二种是预先用map映射编号x对应的节点,本质是一样的。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<string>#include<bitset>#include<algorithm>using namespace std;#define lson th<<1#define rson th<<1|1typedef long long ll;typedef long double ldb;#define inf 99999999#define pi acos(-1.0)#define maxn 200050#define Key_value ch[ch[root][1]][0]pair<int,int>question[maxn];int tot,pos[maxn],s[maxn],e[maxn],qishi[maxn];int t;int cnt,rt;int pre[maxn],ch[maxn][2],sz[maxn],num[maxn];void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d , num= %2d \n",x,ch[x][0],ch[x][1],pre[x],sz[x],num[x]); Treaval(ch[x][1]); }}void debug() {printf("%d\n",rt);Treaval(rt);}void newnode(int &x,int father,int qujian){ x=qujian; //为了方便,这里树上节点的编号就是区间的编号 pre[x]=father;ch[x][0]=ch[x][1]=0; sz[x]=num[x]=e[x]-s[x]+1;}void pushup(int x){ sz[x]=sz[ch[x][0] ]+sz[ch[x][1] ]+num[x];}void build(int &x,int l,int r,int father){ if(l>r)return; int mid=(l+r)/2; newnode(x,father,mid); build(ch[x][0],l,mid-1,x); build(ch[x][1],mid+1,r,x); pushup(x);}void init(){ cnt=rt=0; pre[rt]=ch[rt][0]=ch[rt][1]=sz[rt]=0; build(rt,1,t,0);}void rotate(int x,int p){ int y=pre[x]; ch[y][!p]=ch[x][p]; pre[ch[x][p] ]=y; if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x; pre[x]=pre[y]; ch[x][p]=y; pre[y]=x; pushup(y);pushup(x);}void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x] ]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x];int z=pre[y]; int p=ch[pre[y] ][0]==y; if(ch[y][p]==x )rotate(x,!p); else rotate(y,p); rotate(x,p); } } if(goal==0)rt=x; pushup(x);}int get_kthjiedian(int &x,int k){ int t1=sz[ch[x][0] ]+1; int t2=sz[ch[x][0] ]+num[x]; if(k>=t1 && k<=t2)return x; if(k<t1)return get_kthjiedian(ch[x][0],k); if(k>t2)return get_kthjiedian(ch[x][1],k-t2 );}int get_min(int r){ while(ch[r][0]) { r = ch[r][0]; } return r;}int get_kthweizhi(int r,int k){ int t = sz[ch[r][0]]; if(k <= t)return get_kthweizhi(ch[r][0],k); else if(k <= t + num[r]) return s[r] + k - t - 1; else return get_kthweizhi(ch[r][1],k - t - num[r]);}void del(){ if(ch[rt][0]==0 ){ rt=ch[rt][1]; pre[rt]=0; } else{ int y=ch[rt][0]; int x=ch[rt][1]; while(ch[y][1]){ y=ch[y][1]; } splay(y,rt); ch[y][1]=x; pre[x]=y; rt=y; pre[rt]=0; pushup(rt); }}int bin(int x){ int l = 1, r = t; while(l <= r) { int mid = (l+r)/2; if(s[mid] <= x && x <= e[mid])return mid; if(x < s[mid])r = mid-1; else l = mid+1; } return -1;}int main(){ int n,m,i,j,T,c,d,cas=0; char str[10]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); tot=0; for(i=1;i<=m;i++){ scanf("%s%d",str,&c); if(str[0]=='T')question[i]=make_pair(1,c); else if(str[0]=='Q')question[i]=make_pair(2,c); else question[i]=make_pair(3,c); pos[++tot]=c; } pos[++tot]=1;pos[++tot]=n; sort(pos+1,pos+1+tot); tot=unique(pos+1,pos+1+tot)-pos-1; s[1]=e[1]=pos[1]; t=1; for(i=2;i<=tot;i++){ if(pos[i]-pos[i-1]>1){ t++;s[t]=pos[i-1]+1;e[t]=pos[i]-1; } t++;s[t]=e[t]=pos[i]; } init(); int qujian; printf("Case %d:\n",++cas); for(i=1;i<=m;i++){ c=question[i].first;d=question[i].second; if(c==1){ int r=bin(d); splay(r,0); del(); splay(get_min(rt),0); //这里必须直接把删除的节点放到根节点上,不然会T额。。 ch[r][0] = 0; ch[r][1] = rt; pre[rt] = r; rt = r; pre[rt] = 0; num[rt]=e[rt]-s[rt]+1; pushup(rt); } if(c==2){ qujian=bin(d); splay(qujian,0); printf("%d\n",sz[ch[rt][0] ]+1); } else if(c==3){ printf("%d\n",get_kthweizhi(rt,d)); } } } return 0;}#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<string>#include<bitset>#include<algorithm>using namespace std;#define lson th<<1#define rson th<<1|1typedef long long ll;typedef long double ldb;#define inf 99999999#define pi acos(-1.0)#define maxn 900050#define Key_value ch[ch[root][1]][0]pair<int,int>question[maxn];int tot,pos[maxn],s[maxn],e[maxn],qishi[maxn];int t;map<int,int>mp;map<int,int>::iterator it;int cnt,rt;int pre[maxn],ch[maxn][2],sz[maxn],num[maxn];void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d , num= %2d \n",x,ch[x][0],ch[x][1],pre[x],sz[x],num[x]); Treaval(ch[x][1]); }}void debug() {printf("%d\n",rt);Treaval(rt);}void newnode(int &x,int father){ x=++cnt; pre[x]=father;ch[x][0]=ch[x][1]=0;}void pushup(int x){ sz[x]=sz[ch[x][0] ]+sz[ch[x][1] ]+num[x];}void build(int &x,int l,int r,int father){ if(l>r)return; int mid=(l+r)/2; newnode(x,father); sz[cnt]=num[cnt]=e[mid]-s[mid]+1; qishi[cnt]=s[mid]; if(num[cnt]==1)mp[s[mid]]=cnt; build(ch[x][0],l,mid-1,x); build(ch[x][1],mid+1,r,x); pushup(x);}void init(){ cnt=rt=0; pre[rt]=ch[rt][0]=ch[rt][1]=sz[rt]=0; build(rt,1,t,0);}void rotate(int x,int p){ int y=pre[x]; ch[y][!p]=ch[x][p]; pre[ch[x][p] ]=y; if(pre[y])ch[pre[y] ][ch[pre[y] ][1]==y ]=x; pre[x]=pre[y]; ch[x][p]=y; pre[y]=x; pushup(y);pushup(x);}void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x] ]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x];int z=pre[y]; int p=ch[pre[y] ][0]==y; if(ch[y][p]==x )rotate(x,!p); else rotate(y,p); rotate(x,p); } } if(goal==0)rt=x; pushup(x);}int get_kthjiedian(int &x,int k){ int t1=sz[ch[x][0] ]+1; int t2=sz[ch[x][0] ]+num[x]; if(k>=t1 && k<=t2)return x; if(k<t1)return get_kthjiedian(ch[x][0],k); if(k>t2)return get_kthjiedian(ch[x][1],k-t2 );}int get_kthweizhi(int &x,int k){ int t1=sz[ch[x][0] ]+1; int t2=sz[ch[x][0] ]+num[x]; if(k>=t1 && k<=t2){ int ans=qishi[x]+k-t1; splay(x,0); return ans; } else if(k<t1)return get_kthweizhi(ch[x][0],k); else return get_kthweizhi(ch[x][1],k-t2 );}void del(){ if(ch[rt][0]==0 ){ rt=ch[rt][1]; pre[rt]=0; } else{ int y=ch[rt][0]; int x=ch[rt][1]; while(ch[y][1]){ y=ch[y][1]; } splay(y,rt); ch[y][1]=x; pre[x]=y; rt=y; pre[rt]=0; pushup(rt); }}int get_min(int x){ int r=x; while(ch[r][0]){ r=ch[r][0]; } return r;}int main(){ int n,m,i,j,T,c,d,cas=0; char str[10]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); tot=0; for(i=1;i<=m;i++){ scanf("%s%d",str,&c); if(str[0]=='T')question[i]=make_pair(1,c); else if(str[0]=='Q')question[i]=make_pair(2,c); else question[i]=make_pair(3,c); pos[++tot]=c; } pos[++tot]=1;pos[++tot]=n; sort(pos+1,pos+1+tot); tot=unique(pos+1,pos+1+tot)-pos-1; s[1]=e[1]=pos[1]; t=1; for(i=2;i<=tot;i++){ if(pos[i]-pos[i-1]>1){ t++;s[t]=pos[i-1]+1;e[t]=pos[i]-1; } t++;s[t]=e[t]=pos[i]; } init(); printf("Case %d:\n",++cas); for(i=1;i<=m;i++){ c=question[i].first;d=question[i].second; if(c==1){ int geshu=num[mp[d] ]; int kaishi=qishi[mp[d] ]; splay(mp[d],0); del(); splay(get_min(rt),0 ); cnt++; qishi[cnt]=kaishi; pre[cnt]=0;num[cnt]=geshu; pre[rt]=cnt; ch[cnt][0]=0;ch[cnt][1]=rt; rt=cnt; mp[d]=cnt; pushup(rt); } if(c==2){ splay(mp[d],0); printf("%d\n",sz[ch[rt][0] ]+1); } else if(c==3){ printf("%d\n",get_kthweizhi(rt,d)); } } } return 0;}
0 0
- hdu3436 Queue-jumpers(Splay)
- 【HDU3436】 Queue-jumpers (Splay tree)
- 【Splay】【离散化】hdu3436 Queue-jumpers
- hdu 3436 Queue-jumpers(Splay)
- 【splay tree】 HDOJ Queue-jumpers
- HDU 3436 Queue-jumpers(Splay)
- HDU 3436 Queue-jumpers splay
- hdu3436 splay
- HDU 3436 Queue-jumpers (Splay tree)
- HDU 3436 Queue-jumpers(splay tree)
- hdu 3436 Queue-jumpers(splay tree)
- 【HDU 3436】Queue-jumpers(Splay)
- HDU 3436 Queue-jumpers Splay+离散化
- HDU-3436 Queue-jumpers(Splay树)
- HDU3436[离散化splay]
- Splay树 + 离散化 —— HDU 3436 Queue-jumpers
- HDU 3436 Queue-jumpers splay 离散化 模拟
- hdu 3436 Queue-jumpers
- Spring 读取i18n国际化资源文件的工具类
- 将String日期时间格式转换及截断
- 架构漫谈(四):如何做好架构之架构切分
- UML的简单认识
- POJ 2761Feed the dogs 划分树
- hdu3436 Queue-jumpers(Splay)
- 1002
- webuploader在同一个页面支持多个按钮实例,类似京东那样的评论
- 施密特触发器电路及工作原理
- UIProgressView进度条
- 磁盘 I/O 性能监控指标和调优方法
- git提交A时导致Submitted, Merge Pending, A依赖B(B状态为ABANDONED )
- 【数据结构】 串 YTU 2248: 2280: 找字符个数(串)
- JSP中的EL表达式(1)