hdu3436 splaytree树模拟队列+离散化缩点
数据较大,需要先把每个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树模拟队列+离散化缩点的更多相关文章
- Splay-Tree总结一:模拟队列
伸展树是一种强大的数据结构,由于其特性,可以很好地模拟队列的插队等操作,而线段树解决这类问题通常需要转化一下,比较伤脑筋 而用伸展树的解决方法就是先建好一颗节点数等于队列长度的树,每个队列元素在队列中 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- poj3984迷宫问题 广搜+最短路径+模拟队列
转自:http://blog.csdn.net/no_retreats/article/details/8146585 定义一个二维数组: int maze[5][5] = { 0, 1, 0, ...
- POJ-2528 Mayor's posters (线段树区间更新+离散化)
题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...
- 5. redis管道, 发布订阅, 模拟队列
一. 发布订阅 #订阅scribe 127.0.0.1:6379> SUBSCRIBE "channel_1" Reading messages... (press Ctrl ...
- uva 12100 Printer Queue 优先级队列模拟题 数组模拟队列
题目很简单,给一个队列以及文件的位置,然后一个一个检查,如果第一个是优先级最高的就打印,否则放到队列后面,求所要打印的文件打印需要花费多长时间. 这里我用数组模拟队列实现,考虑到最糟糕的情况,必须把数 ...
- Java集合框架之LinkedList-----用LinkedList模拟队列和堆栈
LinkedList的特有方法: (一)添加方法 addFisrt(E e):将指定元素插入此列表的开头.//参数e可以理解成Object对象,因为列表可以接收任何类型的对象,所以e就是Object对 ...
- 3-08. 栈模拟队列(25)(ZJU_PAT 模拟)
主题链接:http://pat.zju.edu.cn/contests/ds/3-08 设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q. 所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操 ...
- hdu_5818_Joint Stacks(线段树模拟)
题目链接:hdu_5818_Joint Stacks 题意: 给你两个栈,多了个合并操作,然后让你模拟 题解: 很容易想到O(1)的单个栈操作,O(n)的合并操作,这样肯定超时,所以我们要将时间复杂度 ...
随机推荐
- StringUtils中isEmpty 和isBlank的区别
StringUtils在commons-lang-2.2.jar包中:org.apache.commons.lang.StringUtils ; StringUtils方法的操作对象是java.lan ...
- 添加dubbo.xsd的方法
整合dubbo-spring的时候,配置文件会报错 因为 阿里关闭在线的域名了.需要本地下载xsd文件 所以,需要下载本地引入. 解决方式: 在dubbo的开源项目上找到xsd文件: htt ...
- 在tomcat集群下利用redis实现单点登陆
场景:比如说我们要实现一个集群环境,无非是把多个项目部署到多个tomcat下,然后按照一定的算法,轮询什么的随机访问多个tomcat服务器,但是问题也会有许多,比如说,我们最开始是把登陆人的信息存放到 ...
- Ant基础知识1
1.Ant简介 Apache Ant是一个将软件编译/测试/部署等步骤联系在一起加以优化的一个构建工具,常用于java环境中的软件开发.Ant的默认配置文件是build.xml. 对java语言的支持 ...
- python 之禅 import this
dongweiming的博客 前言 我这个博客一直都是一些技术分享,show code的地方,我从来没有写过个人生活或者情感杂谈,当然我也从来没有谈论过我对什么东西的喜恶. 很多人喜欢喷XX语言,喜欢 ...
- 目标提取深度神经网络分析权衡 trade offs
RCNN: 直接使用object proposal 方法得到image crops 送入神经网络中,但是crops 的大小不一样,因此使用 ROI Pooling,这个网络层可以把不同大小的输入映射到 ...
- digest 词根 gest
digest /ˈdaɪdʒest/: to change food that you have just eaten into substances that your body can use; ...
- mysql 语句 GROUP_CONCAT
select * from blog_log;+----+---------------------+-------+--------+| id | time | level | info |+--- ...
- 原生JS给元素添加class属性
有下面这三种简单语句. document.getElementsByTagName('body')[0].className = 'snow-container'; //设置为新的 document ...
- WiFi基本知识【转】
转自:http://blog.csdn.net/myarrow/article/details/7930131 1. IE802.11简介 标准号 IEEE 802.11b IEEE 802.11a ...