hdu3436 Queue-jumpers(Splay)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3411 Accepted Submission(s): 923
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.
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.
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
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)的更多相关文章
- POJ - 3481 splay板子
Double Queue 默写splay板子 很多细节问题... #include<cstdio> #include<iostream> using namespace std ...
- HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...
- 【POJ3481】【splay】Double Queue
Description The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest ...
- POJ 3481Double Queue Splay
#include<stdio.h> #include<string.h> ; ],data[N],id[N],fa[N],size,root; void Rotate(int ...
- HDU 4441 Queue Sequence(splay)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...
- codeforces 38G - Queue splay伸展树
题目 https://codeforces.com/problemset/problem/38/G 题意: 一些人按顺序进入队列,每个人有两个属性,地位$A$和能力$C$ 每个人进入时都在队尾,并最多 ...
- POJ-3481 Double Queue (splay)
The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped w ...
- HDU 3436 Queue-jumpers (splay tree)
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...
- 【splay】文艺平衡树 BZOJ 3223
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...
随机推荐
- ORA-28001: the password has expired解决方法
Oracle提示错误消息ORA-28001: the password has expired,是由于Oracle11G的新特性所致, Oracle11G创建用户时缺省密码过期限制是180天(即6个月 ...
- Spring中的@Valid 和 @Validated注解你用对了吗
1.概述 本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 . 验证用户输入是否正确是我们应用程序中的常见功能.Spring提供了@Valid和@Validated两个注 ...
- Dubbo 配置的加载流程
配置加载流程 在SpringBoot应用启动阶段,Dubbo的读取配置遵循以下原则 Dubbo支持了多层级的配置,按照预先定义的优先级自动实现配置之间的覆盖,最终所有的配置汇总到数据总线URL后,驱动 ...
- mongodb表索引备份,索引的导出导入
背景 发现有两个mongodb环境的数据库表索引不一致,另一个数据库有索引缺失,需要将一个数据库里的所有表索引导入到另一个数据库 也可用于单独备份数据库所有表的索引 写mongo shell的js脚本 ...
- TCP/IP协议栈在Linux内核中的运行时序分析
网络程序设计调研报告 TCP/IP协议栈在Linux内核中的运行时序分析 姓名:柴浩宇 学号:SA20225105 班级:软设1班 2021年1月 调研要求 在深入理解Linux内核任务调度(中断处理 ...
- MySQL的索引优化分析(二)
一.索引优化 1,单表索引优化 建表 CREATE TABLE IF NOT EXISTS article( id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO ...
- (一)React Ant Design Pro + .Net5 WebApi:先搞定服务器,顺手装个Nginx
腾讯云搞定服务器,具体过程就不赘述了,文档都有,咨询客服或者自行百度,体验一下过程. 一. 服务器 1. 云服务器 cvm 1核2G centos8.0 2. 域名注册 www.homejok.com ...
- mybatis入门教程之搭建一个简单的mybatis项目并启动它
一.准备条件: 1.依赖jar包:mybatis核心包(必须).lombok插件包(非必须)以及MySQL数据库连接驱动包(必须) <dependency> <groupId> ...
- DockerFile关键字相关作用以及解释
Dockerfile 关键字 作用 备注 FROM 指定父镜像 指定dockerfile基于那个image构建 MAINTAINER 作者信息 用来标明这个dockerfile谁写的 LABEL 标签 ...
- feign使用okHttpClient,调用原理
最近项目中 spring cloud 用到http请求,使用feign,配置okhttp,打算配置一下就直接使用,不过在压测与调优过程中遇到一些没有预测到的问题,附上排查与解析结 yml.pom配置 ...