Description

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不 过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就 只可能有X-1、X或X+1本书。

当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

Input

第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式:

1. Top S——表示把编号为S的书房在最上面。

2. Bottom S——表示把编号为S的书房在最下面。

3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书;

4. Ask S——询问编号为S的书的上面目前有多少本书。

5. Query S——询问从上面数起的第S本书的编号。

Output

对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

Sample Input

10 10
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 –1
Query 5
Query 2
Ask 2

Sample Output

2
9
9
7
5
3

Hint

100%的数据,n,m <= 80000

题解

其实除了$Splay$,则道题还可以用$Treap$做。

以$key$为关键词,表示其在书架中的位置,若插在两本书中间,直接取$mid$就可以。

$double$有误差,建议一开始就把书架位置的公差调大。

 #include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=;
const int X=0.00000001; struct node
{
double key;
int lev,num,low;
node *child[];
} T[N+],*root,*pos;
double key[N+],miner,maxer;
int n,m,x,y;
char c; void NewNode(node* &r,double key,int num);
void Insert(node* &r,double key,int num);
void Delete(node* &r,double key);
int Query(node* r,int rank,int cnt);
int Ask(node* r,double key);
void Rotate(node* &r,bool t);
int Count(node* r);
double my_abs(double x) {return x< ? -x:x;}
int Read(); int main()
{
srand(time());
root=NULL;
pos=T;
n=Read();
m=Read();
miner=;
maxer=n;
for (int i=;i<=n;i++)
{
x=Read();
key[x]=i;
Insert(root,key[x],x);
}
while(m--)
{
c=;
while(c<'A'||c>'Z') c=getchar();
if (c=='T')
{
x=Read();
Delete(root,key[x]);
key[x]=--miner;
Insert(root,key[x],x);
}
else if (c=='B')
{
x=Read();
Delete(root,key[x]);
key[x]=++maxer;
Insert(root,key[x],x);
}
else if (c=='I')
{
x=Read();
y=Read();
if (y==) continue;
int a=Ask(root,key[x]);
if (a==n-&&y==)
{
Delete(root,key[x]);
key[x]=++maxer;
Insert(root,key[x],x);
continue;
}
if (a==&&y==-)
{
Delete(root,key[x]);
key[x]=--miner;
Insert(root,key[x],x);
continue;
}
Delete(root,key[x]);
if (y==) key[x]=(key[Query(root,a,)]+key[Query(root,a+y,)])/2.0;
else key[x]=(key[Query(root,a+y,)]+key[Query(root,a+y*,)])/2.0;
Insert(root,key[x],x);
}
else if (c=='A')
{
x=Read();
printf("%d\n",Ask(root,key[x])-);
}
else if (c=='Q')
{
x=Read();
printf("%d\n",Query(root,x,));
}
else break;
}
return ;
} int Read()
{
int sum=;
bool ok=;
c=;
while ((c<''||c>'')&&c!='-') c=getchar();
if (c=='-')
{
ok=;
c=getchar();
}
while (c>=''&&c<='')
{
sum=sum*+c-'';
c=getchar();
}
return ok ? -sum:sum;
}
void NewNode(node* &r,double key,int num)
{
r=pos++;
r->key=key;
r->num=num;
r->low=;
r->lev=rand();
}
void Insert(node* &r,double key,int num)
{
if (!r)
{
NewNode(r,key,num);
return;
}
bool t=key>r->key;
if (!t) r->low++;
Insert(r->child[t],key,num);
if (r->child[t]->lev<r->lev)
{
Rotate(r,!t);
r->low=+Count(r->child[]);
}
}
void Delete(node* &r,double key)
{
if (my_abs(r->key-key)<=X)
{
if (r->child[]&&r->child[])
{
bool t=r->child[]->lev<r->child[]->lev;
Rotate(r,t);
r->low=+Count(r->child[]);
if (!t) r->low--;
Delete(r->child[t],key);
}
else
{
if (r->child[]) r=r->child[];
else r=r->child[];
}
}
else
{
bool t=key>r->key;
if (!t) r->low--;
Delete(r->child[t],key);
}
}
void Rotate(node* &r,bool t)
{
node *y=r->child[!t],*R=r;
r->child[!t]=y->child[t];
y->child[t]=r;
r=y;
R->low=+Count(R->child[]);
}
int Query(node* r,int rank,int cnt)
{
//cout<<cnt<<" "<<rank<<" "<<r->low<<endl;
if (r->low+cnt==rank) return r->num;
if (r->low+cnt<rank) return Query(r->child[],rank,r->low+cnt);
if (r->low+cnt>rank) return Query(r->child[],rank,cnt);
}
int Ask(node* r,double key)
{
if (my_abs(r->key-key)<=X) return r->low;
if (r->key<key) return r->low+Ask(r->child[],key);
if (r->key>key) return Ask(r->child[],key);
}
int Count(node* r)
{
if (!r) return ;
return r->low+Count(r->child[]);
}

[ZJOI 2006]书架的更多相关文章

  1. 解题:ZJOI 2006 书架

    题面 学习了如何在维护序列的平衡树上查找某个数:按初始的顺序定个权值,然后每次找那个权值的DFS序即可.具体实现就是不停往上跳,然后是父亲的右儿子就加上父亲的左儿子,剩下的就是继续熟悉无旋树堆 #in ...

  2. [ZJOI 2006]超级麻将

    Description Input 第一行一个整数N(N<=100),表示玩了N次超级麻将. 接下来N行,每行100个数a1..a100,描述每次玩牌手中各种牌的数量.ai表示数字为i的牌有ai ...

  3. [ZJOI 2006]物流运输

    Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...

  4. 解题:ZJOI 2006 皇帝的烦恼

    禁止DP,贪心真香 有一个比较明显的贪心思路是让每个人和距离为$2$(隔着一个人)的人尽量用一样的,这样只需要扫一遍然后对每对相邻的人之和取最大值即可.但是当人数为奇数时这样就会出锅,因为最后一个人和 ...

  5. 解题:ZJOI 2006 游戏排名系统

    题面 跟i207M学了学重载运算符后找前驱后继,然后就是练练无旋树堆 #include<map> #include<cstdio> #include<string> ...

  6. [BZOJ1003](ZJOI 2006) 物流运输trans

    [题目描述] 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格的管理和跟 ...

  7. 【ZJOI 2006】 物流运输

    [题目链接] 点击打开链接 [算法] 令cost(i,j) = 第i天到第j天走相同的路线,路线长度的最小值 那么,只需筛选出第i天到第j天可以装卸货物的码头,然后将这些码头之间连边,跑弗洛伊德(或其 ...

  8. 洛谷 P2585 [ ZJOI 2006 ] 三色二叉树 —— 树形DP

    题目:https://www.luogu.org/problemnew/show/P2585 首先,三色其实记录两种状态:是绿色,不是绿色 即可,因为红蓝可以随意取反: 一开始因为懒得还原出树,所以写 ...

  9. [ ZJOI 2006 ] Trouble

    \(\\\) \(Description\) 有\(N\)个人的环,每个人需要至少\(x_i\)种不同的物品,并且要求任意相邻的两人都没有相同的物品,求最少需要多少种物品. \(N\in [0,2\t ...

随机推荐

  1. Beta阶段敏捷冲刺报告-DAY2

    Beta阶段敏捷冲刺报告-DAY2 Scrum Meeting 敏捷开发日期 2017.11.3 会议时间 13:00 会议地点 微信群 参会人员 项目组全体成员 会议内容 打包问题修复, 爬虫优化, ...

  2. 20145237 实验二 “Java面向对象程序设计”

    20145237 实验二 “Java面向对象程序设计” 实验内容 • 理解并掌握面向对象三要素:封装.继承.多态 • 初步掌握UML建模 • 熟悉S.O.L.I.D原则 • 使用TDD设计实现复数类 ...

  3. SCOI2010 序列操作

    2421 序列操作 http://codevs.cn/problem/2421/ 2010年省队选拔赛四川   题目描述 Description lxhgww最近收到了一个01序列,序列里面包含了n个 ...

  4. 集合Collection总览

    前言 声明,本文使用的是JDK1.8 从今天开始正式去学习Java基础中最重要的东西--->集合 无论在开发中,在面试中这个知识点都是非常非常重要的,因此,我在此花费的时间也是很多,得参阅挺多的 ...

  5. css3动画 一行字鼠标触发 hover 从左到右颜色渐变

    偶然的机会发现的这个东东 这几天做公司的官网 老板突然说出了一个外国网站 我就顺手搜了 并没有发现他说的高科技 但是一个东西深深地吸引了我 就是我下面要说的动画  这个好像不能放视频 我就简单的描述一 ...

  6. Python 列表嵌套多种实现方式

    #coding=utf-8 list=[] for i in range(1,101): list.append(i) # print(list) tempList=[] newList=[] whi ...

  7. python django的ManyToMany简述

    Django的多对多关系 在Django的关系中,有一对一,一对多,多对多的关系 我们这里谈的是多对多的关系 ==我们首先来设计一个用于示例的表结构== # -*- coding: utf-8 -*- ...

  8. LeetCode & Q88-Merge Sorted Array-Easy

    Array Two Pointers Description: Given two sorted integer arrays nums1 and nums2, merge nums2 into nu ...

  9. AngularJS1.X学习笔记12-Ajax

    说到Ajax,你一定是思绪万千,想到XMLHttpRequest,$.ajax(),跨域,异步之类的.本文将探讨一下AngularJS的Ajax. 一.一个简单的例子 <!DOCTYPE htm ...

  10. Python内置函数(49)——isinstance

    英文文档: isinstance(object, classinfo) Return true if the object argument is an instance of the classin ...