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. 跨域的几种方式以及call(),apply() bind()方法的作用和区别

    jsonp: jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议. 一个是描述信息的格式,一个是信息传递 ...

  2. 【JDBC核心】commons-dbutils

    commons-dbutils 简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,它是对 JDBC 的简单封装,学习成本极低,并且使用 commons-d ...

  3. LeetCode704 二分查找

    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1. 示例 1: 输入: num ...

  4. 基于kubernetes实现coredns的及验证

    CoreDNS:  k8s内部的DNS ,用于对pod对service做记录的,好让其他的pod做访问 这里不用做过多的阐述 官方kube-dns现在已经没有在维护了,从Kubernetes 1.11 ...

  5. Git 沙盒模拟实战(远程篇)

    Git 沙盒模拟实战(远程篇) >---基础篇 远程仓库 远程仓库并不复杂, 在如今的云计算盛行的世界很容易把远程仓库想象成一个富有魔力的东西, 但实际上它们只是你的仓库在另个一台计算机上的拷贝 ...

  6. ASP.NET Core错误处理中间件[3]: 异常处理器

    DeveloperExceptionPageMiddleware中间件错误页面可以呈现抛出的异常和当前请求上下文的详细信息,以辅助开发人员更好地进行纠错诊断工作.ExceptionHandlerMid ...

  7. 1.8V升3V芯片,1.8V升3.3V升压芯片方案

    两节干电池由于耗电量电压会降低,无法长期稳定的输出3V或者3.3V供电,直接两节干电池会供电电压不稳,影响后面电路稳定.两节干电池的供电电压在1.8V-3.2V左右 1.8V升3V升压芯片方案, 如P ...

  8. 微信登录2-生成授权URL

    一.准备工作 1.注册 微信开放平台:https://open.weixin.qq.com 2.邮箱激活 3.完善开发者资料 4.开发者资质认证 准备营业执照,1-2个工作日审批.300元 5.创建网 ...

  9. FastAPI实践项目:SayHello(FastAPI + vue.js + axios + element ui)

    目录 简介 翻版 VS 本尊 后端服务 源码 接下来 简介 这次带来的是FastAPI + vue.js + axios + element ui (一个html文件里使用的) 实现的<Flas ...

  10. 分布式跟踪的一个流行标准是OpenTracing API,该标准的一个流行实现是Jaeger项目。

    https://github.com/jaegertracing/jaeger https://mp.weixin.qq.com/s/-Tn2AgyHoq8pwMun8JHcGQ Jaeger的深入分 ...