数据较大,需要先把每个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. python---memcache使用操作

    import memcache mc = memcache.Client(['127.0.0.1:8081'],debug=True) mc.set("key","val ...

  2. python---ORM之SQLAlchemy(2)外键使用

    import sqlalchemy from sqlalchemy import create_engine from sqlalchemy import Column,String,Integer, ...

  3. mac下chrome快捷键

    打开开发者工具:alt + command + I: 打开“JavaScript 控制台”:⌘-Option-J: 打开当前网页的源代码:⌘-Option-U: 刷新页面:command + R: m ...

  4. Docker部署Consul集群

    服务介绍 Consul是一种分布式.高可用.支持水平扩展的服务注册与发现工具.包含的特性有:服务发现.健康检查.键值存储.多数据中心和服务管理页面等. 官方架构设计图: 图中包含两个Consul数据中 ...

  5. VUE2.0 饿了吗视频学习笔记(三):VUE2.0取消了v-link

    https://gitee.com/1981633/vue_study.git 源码下载地址,随笔记动态更新中 写法如下 <div class="tab-item"> ...

  6. ettercap插件介绍

    利用sslstrip和ettercap突破ssl嗅探密码 ettercap之DNS欺骗--结合metasploit使用 ettercap支持在运行时加载模块.它们会自动地编译你的系统是否支持他们或者直 ...

  7. Ribbon实现Office开始菜单

    Ribbon实现Office开始菜单 界面效果: 首先:在主窗体上拖入popupMenu控件和imageCollection控件 然后选中popupMenu点击三角,再点击Run Designer在弹 ...

  8. POJ1751 Highways【最小生成树】

    题意: 给你N个城市的坐标,城市之间存在公路,但是由于其中一些道路损坏了,需要维修,维修的费用与公路长成正比(公路是直的). 但现有M条公路是完整的,不需要维修,下面有M行,表示不需要维修的道路两端的 ...

  9. [POI2007]ZAP-Queries (莫比乌斯反演+整除分块)

    [POI2007]ZAP-Queries \(solution:\) 唉,数论实在有点烂了,昨天还会的,今天就不会了,周末刚证明的,今天全忘了,还不如早点写好题解. 这题首先我们可以列出来答案就是: ...

  10. TCP3次握手和4次挥手及其为什么

    TCP 3次握手 客户端向服务器发送一个SYN(包含了SYN,SEQ). 当服务器接收到客户端发过来的SYN时,会向客户端发送一个SYN+ACK的数据包,其实ACK的ack等于上一次发送SYN数据包的 ...