题解:

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的模板题····

md表示insert操作脑残了·····又是删点又是加点的···导致直接t····

最后发现直接交换两者的pos和val就可以了···我tm·······

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=1e5+;
int father[N],son[N][],val[N],size[N],root,tot,pos[N];
int n,m,a,b;
char s[];
inline int R()
{
char c;int f=,i=;
for(c=getchar();(c<''||c>'')&&(c!='-');c=getchar());
if(c=='-')
i=-,c=getchar();
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f*i;
}
inline void clear(int now)
{
father[now]=son[now][]=son[now][]=size[now]=;
}
inline void update(int now)
{
if(now)
{
size[now]=;
if(son[now][]) size[now]+=size[son[now][]];
if(son[now][]) size[now]+=size[son[now][]];
}
}
inline int get(int now)
{
return son[father[now]][]==now;
}
inline void rotate(int now)
{
int fa=father[now],ofa=father[fa],which=get(now);
son[fa][which]=son[now][which^],father[son[fa][which]]=fa;
son[now][which^]=fa,father[fa]=now,father[now]=ofa;
if(ofa) son[ofa][son[ofa][]==fa]=now;
update(fa),update(now);
}
inline void splay(int now,int to)
{
while(father[now]!=to)
{
if(father[father[now]]!=to) rotate(get(now)==get(father[now])?father[now]:now);
rotate(now);
}
if(!to) root=now;
}
inline void build(int x)
{
int now=root,last=;
while(true)
{
if(!now)
{
now=++tot;father[now]=last;size[now]=;val[now]=x;pos[x]=now;
if(last) son[last][]=now;update(last);
splay(now,);
break;
}
last=now;
now=son[now][];
}
}
inline int find(int x) //找到第x本的编号
{
int now=root;
while(true)
{
if(x<=size[son[now][]]) now=son[now][];
else
{
int temp=size[son[now][]]+;
if(x==temp) {return val[now];}
x-=temp;now=son[now][];
}
}
}
inline int pre()
{
int now=son[root][];
while(son[now][]) now=son[now][];
return now;
}
inline int next()
{
int now=son[root][];
while(son[now][]) now=son[now][];
return now;
} inline void Delete(int x) //找到编号为x的书将其删除
{
splay(pos[x],);
if(!son[root][]){int oldroot=root;root=son[root][];father[root]=;clear(oldroot);return;}
if(!son[root][]){int oldroot=root;root=son[root][];father[root]=;clear(oldroot);return;}
else
{
int leftbig=pre(),oldroot=root;
splay(leftbig,);
son[root][]=son[oldroot][];
father[son[root][]]=root;
update(root);clear(oldroot);
return;
}
}
inline void findtop()//找到最上面的书并将其旋转至根节点
{
int now=root;
while(son[now][]) now=son[now][];
splay(now,);
}
inline void findbot()
{
int now=root;
while(son[now][]) now=son[now][];
splay(now,);
}
inline void inserttop(int x) //把x放在书的最上面
{
Delete(x);findtop();
son[root][]=pos[x];
father[pos[x]]=root;size[pos[x]]=;son[pos[x]][]=son[pos[x]][]=;
update(root);
}
inline void insertbot(int x) //把x放在书的最下面
{
Delete(x);findbot();
son[root][]=pos[x];
father[pos[x]]=root;size[pos[x]]=;son[pos[x]][]=son[pos[x]][]=;
update(root);
}
int main()
{
//freopen("a.in","r",stdin);
n=R(),m=R();
for(int i=;i<=n;i++)
a=R(),build(a);
while(m--)
{
scanf("%s",s);
if(s[]=='T') {a=R();inserttop(a);}
if(s[]=='B') {a=R();insertbot(a);}
if(s[]=='I')
{
a=R(),b=R();
if(!b) continue;
else
{
splay(pos[a],);int temp,flag=;
if(b==) continue;
if(b==-) temp=pre();
if(b==) temp=next();
int t1=val[temp],t2=pos[a];
swap(pos[t1],pos[a]);
swap(val[t2],val[temp]);
}
}
if(s[]=='A')
{
a=R();splay(pos[a],);
if(!son[root][])
cout<<""<<endl;
else
cout<<size[son[root][]]<<endl;
}
if(s[]=='Q')
a=R(),cout<<find(a)<<endl;
}
return ;
}

刷题总结——书架(bzoj1861)的更多相关文章

  1. LeetCode刷题总结-动态规划篇

    本文总结LeetCode上有动态规划的算法题,推荐刷题总数为54道.具体考点分析如下图: 1.中心扩展法 题号:132. 分割回文串 II,难度困难 2.背包问题 题号:140. 单词拆分 II,难度 ...

  2. LeetCode刷题系列

    LeetCode 我们工作面试和提高自身数据结构和算法能力的时候往往需要刷刷题,我选择LeetCode是通过一个留学论坛了解的.专业,覆盖语种全面. 提前说说刷题的心得: 尽量手写代码,少使用IDE的 ...

  3. ife任务刷题总结(一)-css reset与清除浮动

    本文同时发布于本人的个人网站www.yaoxiaowen.com 百度创办的前端技术学院,是一个面向大学生的前端技术学习平台.虽然只有大学生才有资格报名,提交代码进行比赛排名.但是这并不妨碍我们这些初 ...

  4. 刷题ING...

    我用codeVS刷题.. 努力准备!!

  5. XidianOJ 1020 ACMer去刷题吧

    题目描述 刷题是每个ACMer必由之路,已知某oj上有n个题目,第i个题目小X能做对的概率为Pi(0<=Pi<=1,1<=i<=n) 求小X至少做对k道题的概率 输入 第一行输 ...

  6. 【BZOJ-4590】自动刷题机 二分 + 判定

    4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 156  Solved: 63[Submit][Status ...

  7. NOI题库分治算法刷题记录

    今天晚自习机房刷题,有一道题最终WA掉两组,极其不爽,晚上回家补完作业欣然搞定它,特意来写篇博文来记录下 (最想吐槽的是这个叫做分治的分类,里面的题目真的需要分治吗...) 先来说下分治法 分治法的设 ...

  8. NOI题库刷题日志 (贪心篇题解)

    这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制:  1000ms  内存限制:  65536kB 描述 在一个平面上,如果有两个点( ...

  9. 用js刷题的一些坑

    leecode可以用js刷题了,我大js越来越被认可了是吧.但是刷题中会因为忽略js的一些特性掉入坑里.我这里总结一下我掉过的坑. 坑1:js中数组对象是引用对象 js中除了object还有数组对象也 ...

随机推荐

  1. Redis性能优化之redis.cnf配置参数

    redis调优总结 1.相应的参数调优 加内存2.redis使用结构调优3.使用合理的数据类型说明:redis存储的数据为redis hash(字符映射表) 单key多字段结构. 1)调整配置文件中配 ...

  2. iPhone开发小工具

    1.AppIcon: 可以瞬间把图片转换为应用所需要的Icon(Icon-72.png,Icon-72@2x.png,......iTunesArtwork@2x)   2.Resizer: 方便把- ...

  3. hdu 6058 Kanade's sum (计算贡献,思维)

    题意: 给你一个全排列,要你求这个序列的所有区间的第k大的和 思路:比赛的时候一看就知道肯定是算贡献,也知道是枚举每个数,然后看他在多少个区间是第K大,然后计算他的贡献就可以了,但是没有找到如何在o( ...

  4. const、let、var的区别

    const不能从字面上来理解,他不能修改的是栈内存在的值和地址. 使用const声明的是常量,在后面出现的代码中不能再修改该常量的值. 怎么理解栈内存在的值和地址呢?就要从javascript的类型说 ...

  5. Codeforces Round #277.5 (Div. 2)-D. Unbearable Controversy of Being

    http://codeforces.com/problemset/problem/489/D D. Unbearable Controversy of Being time limit per tes ...

  6. java HttpServletRequest 重复流读取

    在用reset接口的时候,常常会使用request.getInputStream()方法,但是流只能读取一次,一旦想要加上一个过滤器用来检测用户请求的数据时就会出现异常.   在过滤器中通过流读取出用 ...

  7. 随机生成一份试卷,试卷的种类分为单选、多选、判断三种题型。nodejs6.0 mysql

    背景:从数据库中,随机生成一份试卷,试卷的种类分为单选.多选.判断三种题型. 首先我需要生成随机数id(在这之前我需要知道数据库中各个题型的题数,这样我才能设置随机数),并依据生成的随机数id,去查找 ...

  8. 各种排序算法(JS实现)

    目录: 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序,归并排序.桶排序.基数排序.多关键字排序.总结 JS测试代码 function genArr(){ let n = Math. ...

  9. Linux 磁盘相关

    挂载文件系统 mount mount [-t fstype] filesystem dir ##mount /dev/sdb /data 卸载文件系统 umount umount /dev/sdb u ...

  10. Django中重定向页面的时候使用命名空间

    urls.py from django.urls import path from . import views app_name='front' urlpatterns = [ path('',vi ...