P2596 [ZJOI2006]书架

题目描述

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

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

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

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

输入输出格式

输入格式:

第一行有两个数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本书的编号。

输出格式:

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

说明

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


这是我做的第一道非板子的平衡树题目,写+调大概花了2个小时,稍稍有点困,先以时间压到1个小时为目标了。

很显然,这颗平衡树是一颗区间树,用来平衡的域是书的相对位置大小,我们用树的大小信息来查询某个点在书架的相对位置,而不去直接存储这个相对位置以比较,这应该是区间树的一个重要特点。

用\(pos[i]\)维护编号为\(i\)的书对应哪个节点。

对于操作:

放在最上面/下面就先删掉然后加点

添加的话只有两个情况,就先把要添加的节点伸展到根,然后和它的前驱/后继交换即可

两个询问互为逆操作,有关排名的


#include <cstdio>
#include <iostream>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
#define f t[now].par
#define s t[now].ch[typ]
using namespace std;
const int N=160010;
struct Splay
{
int ch[2],par,siz,num;
}t[N];
int root,tot=0,n,m,x,a[N],pos[N];//编号为i的书对应的当前点的编号
string S;
int identity(int now)
{
return t[f].ch[1]==now;
}
void connect(int fa,int now,int typ)
{
f=fa;
t[fa].ch[typ]=now;
}
void updata(int now)
{
t[now].siz=t[ls].siz+t[rs].siz+1;
}
void rotate(int now)
{
int p=f,typ=identity(now);
connect(p,t[now].ch[typ^1],typ);
connect(t[p].par,now,identity(p));
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now,int to)
{
to=t[to].par;
for(int typ;f!=to;rotate(now))
if(t[f].par!=to)
rotate(identity(now)==identity(f)?f:now);
if(!to) root=now;
}
int New(int dat)
{
t[++tot].num=dat;t[tot].siz=1;return tot;
}
void free(int now)
{
t[now].num=0;t[now].siz=0;t[now].par=0;ls=0;rs=0;
if(tot==now) tot--;
}
void find(int x)//当前排名为x的书的编号
{
int now=root;
while(t[ls].siz+1!=x)
now=t[now].ch[t[ls].siz+1<x?x-=t[ls].siz+1,1:0];
splay(now,root);
printf("%d\n",t[now].num);
}
int get_max(int now,int typ)
{
if(typ) t[now].siz++;
return rs?get_max(rs,typ):now;
}
int get_min(int now,int typ)
{
if(typ) t[now].siz++;
return ls?get_min(ls,typ):now;
}
void extrack(int now)//删除编号为now的点
{
splay(now,root);
if(!ls){root=rs;connect(0,root,1);free(now);return;}
int rt=get_max(ls,0);
splay(rt,ls);
connect(rt,rs,1);
connect(0,rt,1);
updata(rt);
root=rt;
free(now);
}
void rank(int now)
{
splay(now,root);
printf("%d\n",t[ls].siz);
}
void top(int now,int num)//节点编号和书的编号
{
extrack(now);
int fa=get_min(root,1);
connect(fa,now=New(num),0);
pos[num]=now;
updata(now);
}
void bottom(int now,int num)
{
extrack(now);
int fa=get_max(root,1);
connect(fa,now=New(num),1);
pos[num]=now;
updata(now);
}
void exchange(int to,int now)
{
swap(pos[t[to].num],pos[t[now].num]);
swap(t[to].num,t[now].num);
}
void insert(int now,int T)
{
if(!T) return;
splay(now,root);
if(T==1) exchange(get_min(rs,0),now);
else exchange(get_max(ls,0),now);
}
int build(int l,int r,int fa)
{
if(l>r) return 0;
int now=l+r>>1;
t[now].par=fa;
t[now].num=a[now];
updata(now);
if(l==r) return now;
ls=build(l,now-1,now);
rs=build(now+1,r,now);
updata(now);
return now;
}
/*void write(int now)
{
if(!now) return;
write(ls);
printf("%d ",t[now].num);
write(rs);
}*/
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
pos[a[i]]=i;
}
connect(0,root=build(1,n,0),1);
tot=n;
for(int i=1;i<=m;i++)
{
cin>>S;
scanf("%d",&x);
if(S=="Top")
top(pos[x],x);
else if(S=="Bottom")
bottom(pos[x],x);
else if(S=="Insert")
{
int T;scanf("%d",&T);
insert(pos[x],T);
}
else if(S=="Ask")
rank(pos[x]);
else
find(x);
//write(root);
//printf("%d\n");
}
return 0;
}

2018.6.14

洛谷 P2596 [ZJOI2006]书架 解题报告的更多相关文章

  1. [洛谷P2596] [ZJOI2006]书架

    洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...

  2. 洛谷 P2596 [ZJOI2006]书架 (splay)

    题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...

  3. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  4. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  5. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  6. 洛谷 P3349 [ZJOI2016]小星星 解题报告

    P3349 [ZJOI2016]小星星 题目描述 小\(Y\)是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有\(n\)颗小星星,用\(m\)条彩色的细线串了起来,每条细线连着两颗小星星. 有一 ...

  7. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  8. 洛谷 P4705 玩游戏 解题报告

    P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...

  9. 洛谷 P1272 重建道路 解题报告

    P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...

随机推荐

  1. Luogu P1306 斐波那契公约数

    这道题其实是真的数学巨佬才撸的出来的题目了 但如果只知道结论但是不知道推导过程的我感觉证明无望 首先这道题肯定不能直接搞,而且题目明确说明了一些方法的问题 所以就暗示我们直接上矩阵了啦 但是如果直接搞 ...

  2. SA的一个辣鸡trick

    基础板子 namespace SA{ int x[400010],y[400010],SA[400010],rk[400010],ht[400010],t[400010]; int st[19][40 ...

  3. 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--控制器的声明定义和发现篇(3/8)

    文章目录 前情概要 前面文章把路由已经介绍的差不多了,包括url映射,路由选择等.接下来讲一讲controller的一些基本规则 BaseController的所有代码都在这里拉.相当简单. 主要逻辑 ...

  4. nginx的web缓存服务环境部署记录

    web缓存位于内容源Web服务器和客户端之间,当用户访问一个URL时,Web缓存服务器会去后端Web源服务器取回要输出的内容,然后,当下一个请求到来时,如果访问的是相同的URL,Web缓存服务器直接输 ...

  5. 2017乌鲁木齐区域赛D题Fence Building-平面图的欧拉公式

    这个题B站上面有这题很完整的分析和证明,你实在不懂,可以看看这个视频  https://www.bilibili.com/video/av19849697?share_medium=android&a ...

  6. 第三次Sprint-最后冲刺

    由于一些原因,导致我和汝婷被退队了.因此我们是从上星期重新开始做系统. 陈汝婷单独负责: 1.用户输入题目数: 2.限制题数: 3.自动生成用户需要题目数的题目: 4.计时 练丽云单独: 1.异常处理 ...

  7. [转]java实现,输入数据,空格继续,回车结束输入

    普通版:可输入,可输出.带详细的注释 import java.util.Scanner; public class SumDemo { public static void main(String[] ...

  8. Chrome 启动参数列表

    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --type=gpu-process --channel ...

  9. redux的源码解析

    一. redux出现的动机 1. Javascript 需要管理比任何时候都要多的state2. state 在什么时候,由于什么原因,如何变化已然不受控制.3. 来自前端开发领域的新需求4. 我们总 ...

  10. Jquery ajax 数据更新

    $(function(){ var $personWifePs=$("#wife-money tbody tr"); var $personWife=$("#wife-m ...