Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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.
 

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

题意:给你一个长为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|1
typedef 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|1
typedef 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;
}

hdu3436 Queue-jumpers(Splay)的更多相关文章

  1. POJ - 3481 splay板子

    Double Queue 默写splay板子 很多细节问题... #include<cstdio> #include<iostream> using namespace std ...

  2. HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...

  3. 【POJ3481】【splay】Double Queue

    Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest ...

  4. POJ 3481Double Queue Splay

    #include<stdio.h> #include<string.h> ; ],data[N],id[N],fa[N],size,root; void Rotate(int ...

  5. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  6. codeforces 38G - Queue splay伸展树

    题目 https://codeforces.com/problemset/problem/38/G 题意: 一些人按顺序进入队列,每个人有两个属性,地位$A$和能力$C$ 每个人进入时都在队尾,并最多 ...

  7. POJ-3481 Double Queue (splay)

    The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped w ...

  8. HDU 3436 Queue-jumpers (splay tree)

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

随机推荐

  1. Centos 6 下安装 OSSEC-2.8.1 (一)

    ossec -2.8.1 安装: ## 1 ) 安装依赖包: RedHat / Centos / Fedora / Amazon Linux yum install -y pcre mysql mys ...

  2. Mac Navicat premium 12 连接mysql8.0.21出现 'caching_sha2_password' 解决方案

    1.通过命令 select user,plugin from user where user='root'; 我们可以发现加密方式是caching_sha2_password. 2.  修改查看加密方 ...

  3. mysql过滤复制

  4. OpenID协议

    背景 当我们要使用一个网站的功能时,一般都需要注册想用的账号.现在的互联网应用很多,一段时间之后你会发现你注册了一堆账号密码,根本记不住. 你可能会想到所有的网站都用同一套用户名和密码,这样虽然能解决 ...

  5. ctfhub技能树—文件上传—文件头检查

    打开靶机 尝试上传一个php文件 抓包修改 放包 制作图片马 上传图片马,并修改文件类型为png 测试连接 查找flag 成功拿到flag

  6. LuoguP5075 [JSOI2012]分零食

    题意 有\(A\)个人,\(m\)个糖,你可以选择一个\(k\),使第\(1\)$k$个人每个人至少得到一个糖,并且第$k+1$\(A\)个人都得不到糖.\(m\)个糖必须给完.对于每个方案都有一个欢 ...

  7. SpringBoot 好“吃”的启动原理

    原创:西狩 编写日期 / 修订日期:2020-12-30 / 2020-12-30 版权声明:本文为博主原创文章,遵循 CC BY-SA-4.0 版权协议,转载请附上原文出处链接和本声明. 不正经的前 ...

  8. C# Twain协议调用扫描仪,设置多图像输出模式(Multi image output)

    Twain 随着扫描仪.数码相机和其他图像采集设备的引入,用户热切地发现了将图像整合到他们的文档和其他工作中的价值.然而,支持这种光栅数据的显示和操作成本很高,应用程序开发人员需要创建用户界面并内置设 ...

  9. 2 安装部署flume

    本文对flume进行安装部署 flume是什么?传送门:https://www.cnblogs.com/zhqin/p/12230301.html 0.要安装部署在日志所在的服务器,或者把日志发送到日 ...

  10. libuv事件循环中的三种句柄

    1.说明 本文会简单介绍 libuv 的事件循环,旨在入门级别的使用,而不做深入探究,简单来说就是,会大概用就行,先用熟练了,再去探究原理和源码 下图为官网的 libuv 的不同部分及其涉及的子系统的 ...