数据较大,需要先把每个top不会操作到的段缩成一个点,记录其开始和结束的位置,和top能操作到的点一起建立一颗伸展树模拟

然后就是普通的队列模拟操作

/*
不会被top操作到的区间就缩点
通过splay tree模拟出序列,初始序列的第i个缩点对应的树结点也是i
操作top a:找到结点a,将其移到最左边
query a:结点a的左边有多少人
rank a:第a个结点是第几个结点
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 100005
#define L ch[r][0]
#define R ch[r][1]
using namespace std; int pre[maxn],ch[maxn][],size[maxn],num[maxn],root,tot;
int s[maxn],e[maxn],cnt;
void debug();
inline void newnode(int &r,int fa,int k){
r=k;
ch[r][]=ch[r][]=;
pre[r]=fa;
size[r]=num[r]=e[k]-s[k]+;
}
inline void pushup(int r){
size[r]=size[L]+size[R]+num[r];
}
void build(int &x,int l,int r,int fa){
if(l>r) return;
int mid=l+r>>;
newnode(x,fa,mid);
build(ch[x][],l,mid-,x);
build(ch[x][],mid+,r,x);
pushup(x);
}
void init(int n){
root=tot=;
size[root]=pre[root]=ch[root][]=ch[root][]=;
build(root,,n,);
}
void Rotate(int x,int kind)
{
int y = pre[x];
//pushdown(y);
//pushdown(x);//先把y的标记下传,在把x的标记下传
ch[y][!kind] = ch[x][kind];
pre[ch[x][kind]] = y;
if(pre[y])
ch[pre[y]][ch[pre[y]][]==y] = x;
pre[x] = pre[y];
ch[x][kind] = y;
pre[y] = x;
pushup(y);
}
//Splay调整,将r结点调整到goal下面
void splay(int r,int goal)
{
//push_down(r);
while(pre[r] != goal)
{
if(pre[pre[r]] == goal)
Rotate(r,ch[pre[r]][]==r);
else
{
int y = pre[r];
int kind = ch[pre[y]][]==y;
if(ch[y][kind] == r)
{
Rotate(r,!kind);
Rotate(r,kind);
}
else
{
Rotate(y,kind);
Rotate(r,kind);
}
}
}
pushup(r);
if(goal == ) root = r;
}
int getmin(int r){while(L) r=L;return r;}
void del(){
int t=root;
if(ch[root][]){
root=ch[root][];
splay(getmin(root),);
ch[root][]=ch[t][];
if(ch[root][]) pre[ch[root][]]=root;
}
else root=ch[root][];
pre[root]=;
pushup(root);
}
int Bin(int x){//二分查找x属于那一段
int l=,r=cnt;
while(l<=r){
int mid=l+r>>;
if(s[mid]<=x && e[mid]>=x) return mid;
if(x<s[mid]) r=mid-;
else l=mid+;
}
return -;
}void Treavel(int x)
{
if(x)
{
Treavel(ch[x][]);
printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d num = %2d s = %2d e = %2d\n",x,ch[x][],ch[x][],pre[x],size[x],num[x],s[x],e[x]);
Treavel(ch[x][]);
}
}
void debug()
{
printf("root:%d\n",root);
Treavel(root);
}
void top(int x){//把结点r移到最左边
int r=Bin(x);
splay(r,);
del(); ch[r][]=;
ch[r][]=root;
pre[root]=r;
root=r;
pre[root]=;
pushup(root);
//debug();
}
int query(int x){//结点x左边有多少结点
int r=Bin(x);
splay(r,);
return size[ch[root][]]+x-s[r]+;
}
int rankk(int r,int k){//排在第k位的结点
int t=size[ch[r][]];
if(k<=t) return rankk(ch[r][],k);
else if(k<=t+num[r]) return s[r]+k-t-;
else return rankk(ch[r][],k-t-num[r]);
} char op[maxn][];
int qnum[maxn],p[maxn]; int main(){
int n,q,T;
scanf("%d",&T);
for(int tt=;tt<=T;tt++){
scanf("%d%d",&n,&q);
int t=;
for(int i=;i<q;i++){
scanf("%s%d",op[i],&qnum[i]);
if(op[i][]=='T')
p[t++]=qnum[i];
}
p[t++]=;
p[t++]=n;
sort(p,p+t);
t=unique(p,p+t)-p;
cnt=;
for(int i=;i<t;i++){
if(i> && p[i]-p[i-]>){
cnt++;
s[cnt]=p[i-]+;
e[cnt]=p[i]-;
}
cnt++;
s[cnt]=p[i];e[cnt]=p[i];
}
init(cnt);
// debug();
printf("Case %d:\n",tt);
for(int i=;i<q;i++){
// debug();
if(op[i][]=='T') top(qnum[i]);
else if(op[i][]=='Q') printf("%d\n",query(qnum[i]));
else printf("%d\n",rankk(root,qnum[i]));
// debug();
}
}
return ;
}

hdu3436 splaytree树模拟队列+离散化缩点的更多相关文章

  1. Splay-Tree总结一:模拟队列

    伸展树是一种强大的数据结构,由于其特性,可以很好地模拟队列的插队等操作,而线段树解决这类问题通常需要转化一下,比较伤脑筋 而用伸展树的解决方法就是先建好一颗节点数等于队列长度的树,每个队列元素在队列中 ...

  2. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  3. poj3984迷宫问题 广搜+最短路径+模拟队列

    转自:http://blog.csdn.net/no_retreats/article/details/8146585   定义一个二维数组: int maze[5][5] = { 0, 1, 0, ...

  4. POJ-2528 Mayor's posters (线段树区间更新+离散化)

    题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...

  5. 5. redis管道, 发布订阅, 模拟队列

    一. 发布订阅 #订阅scribe 127.0.0.1:6379> SUBSCRIBE "channel_1" Reading messages... (press Ctrl ...

  6. uva 12100 Printer Queue 优先级队列模拟题 数组模拟队列

    题目很简单,给一个队列以及文件的位置,然后一个一个检查,如果第一个是优先级最高的就打印,否则放到队列后面,求所要打印的文件打印需要花费多长时间. 这里我用数组模拟队列实现,考虑到最糟糕的情况,必须把数 ...

  7. Java集合框架之LinkedList-----用LinkedList模拟队列和堆栈

    LinkedList的特有方法: (一)添加方法 addFisrt(E e):将指定元素插入此列表的开头.//参数e可以理解成Object对象,因为列表可以接收任何类型的对象,所以e就是Object对 ...

  8. 3-08. 栈模拟队列(25)(ZJU_PAT 模拟)

    主题链接:http://pat.zju.edu.cn/contests/ds/3-08 设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q. 所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操 ...

  9. hdu_5818_Joint Stacks(线段树模拟)

    题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...

随机推荐

  1. 仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'Address'中的标识列指

    在有自增长的SQL表格里面插入指定ID的数据的时候,会禁止你操作,提示如题目,解决办法: set identity_insert address on ,,,) set identity_insert ...

  2. JavaSE学习总结(十)—— JDBC与面向对象测试

    一.题目 请使用MySQL+JDBC+JAVASE控制台完成一个图书管理系统(Libs),实现添加图书,查询图书,根据图书编号查询图书三个功能. 二.要求 1.必须有菜单 2.至少3个以上的字段(编号 ...

  3. .Net进阶系列(13)-异步多线程(Task和Parallel)(被替换)

    一. Task开启多线程的三种形式 1. 利用TaskFactory下的StartNew方法,向StartNew传递无参数的委托,或者是Action<object>委托. 2. 利用Tas ...

  4. 词典的实现(1)--Map的底层实现

    1,词典是这样的一种数据结构:它能根据给定的键(索引值,key)来查找其对应的值(value)是否存在,在JAVA中主要由java.util.HashMap来完成该功能.如电话本就是词典的一个具体实例 ...

  5. Python3.X爬虫

    1.Python很有名,但是一直没在实际项目中用过,今天花30分钟学习下.去Python官网https://www.python.org/downloads/ 2.2.X与3.X版本相差比较大,新手用 ...

  6. 三、编译第一步 make xxx_defconfig——Makefile.build 脚本

    3.1 上章分析回顾 3.1 上章分析出的参数 3.1.1 变量 MAKECMDGOALS = xxx_defconfig KBUILD_EXTMOD = version_h := include/g ...

  7. 二、ARM处理器

    2.1 介绍 ARM核心的基本结构指ARM架构显示处理器中处理的数据大小.指令架构.寄存器等的结构和运行原理 ARM核心是利用ARM架构的基本原理实现的处理器核心部分. ARM的主要架构如下: ARM ...

  8. 20155334 2016-2017-2 《Java程序设计》第九周学习总结

    20155334 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十六章:整合数据库 16.1 JDBC入门 JDBC(Java DataBase Conn ...

  9. mysql 案例 ~查询导致的tmp临时文件问题

    一 简介:之前遇到一个tmp分区暴涨的问题,后来经过大神的指点,遂分析写下 二 分类: 1  select语句出现 using temporay tmp 下出现 #sql_631a_1.MYD #sq ...

  10. Java编程:悲观锁、乐观锁的区别及使用场景

    定义: 悲观锁(Pessimistic Lock): 每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁.由于 ...