您的位置:首页 > 其它

splay学习小结1.1【BZOJ 1861】[Zjoi2006]Book 书架

2017-03-02 22:31 465 查看

1.1

早几天以为splay是以权值为关键字的,然后做这题的时候一脸懵逼。

然后才知道这个东西也可以以位置为关键字

操作的话大体都是相同的,但是search操作可以变成直接用一个数组来使得权值和节点编号一一对应

这一题是位置为关键字的模板题,所以说操作都比较好想

TOP,BOTTLE的话就直接把节点1或节点n splay一下,然后直接插入

INSERT的话就直接把两个节点对应的权值互换一下就好了

但是有很多越界方面的细节要谨慎的处理

题目

1861: [Zjoi2006]Book 书架

Time Limit: 4 Sec Memory Limit: 64 MB

Submit: 639 Solved: 372

[Submit][Status]

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

Source

Day2

贴代码

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;

const int maxn=100005;
int father[maxn],data[maxn],cnt[maxn],a[maxn],dui[maxn];
int son[maxn][5];
int i,j,k,l,n,m,root,t1,t2,x,y,z,tot,tmp;
char s[15];

void rotate(int x,int w){
int y;
y=father[x];
cnt[y]=cnt[y]-cnt[x]+cnt[son[x][w]];
cnt[x]=cnt[x]+cnt[y]-cnt[son[x][w]];
father[x]=father[y];
if (father[y]) {
if (son[father[y]][1]==y) son[father[y]][1]=x; else son[father[y]][2]=x;
}
son[y][3-w]=son[x][w];
if (son[x][w]) father[son[x][w]]=y;
father[y]=x; son[x][w]=y;
}

void splay(int x){
int y;
while (father[x]) {
y=father[x];
if (!father[y]){
if (x==son[y][1]) rotate(x,2); else rotate(x,1);
} else {
if (y==son[father[y]][1]){
if (x==son[y][1]) {
rotate(y,2); rotate(x,2);
}
else {
rotate(x,1); rotate(x,2);
}
} else {
if (x==son[y][1]) {
rotate(x,2); rotate(x,1);
} else {
rotate(y,1); rotate(x,1);
}
}
}
}
root=x;
}
int search(int x,int w){
splay(dui[w]);
return dui[w];
}

int kth(int x,int w){
int i;
i=root;
while ((x!=cnt[son[i][w]]+1) && (i)) {
if (x<cnt[son[i][w]]+1){
i=son[i][w];
} else {
x=x-cnt[son[i][w]]-1;
i=son[i][3-w];
}
}
splay(i);
return root;
}

int findnum(int x,int w){
int tmp;
tmp=search(root,x);
return cnt[son[root][w]];
}

void del(int x){
int y,k;
k=search(root,x);
y=son[k][1];
if (son[k][1]==0){
y=son[k][2]; son[k][2]=0; data[k]=0; cnt[k]=0; father[y]=0; root=y;
}
father[y]=0;
while (son[y][2]) y=son[y][2];
if (y==0) y=son[k][2];
splay(y);
son[root][2]=son[k][2];
cnt[root]=cnt[root]+cnt[son[k][2]];
if (son[root][2]) father[son[root][2]]=root;
son[k][1]=0; son[k][2]=0; cnt[k]=0; data[k]=0;
}
int main(){
//freopen("1861.in","r",stdin);
//freopen("1861.out","w",stdout);
root=0;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++){
scanf("%d",&a[i]);
father[i]=i-1;
if (i!=1) son[i-1][2]=i;
data[i]=a[i]; cnt[i]=n-i+1;
dui[a[i]]=i;
}
root=1;
for (i=1;i<=m;i++){
scanf("%s",&s);
scanf("%d",&t1);
if (s[0]=='Q'){
printf("%d\n",data[kth(t1,1)]);
} else
if (s[0]=='A'){
printf("%d\n",findnum(t1,1));
} else
if (s[0]=='T'){
del(t1);
t2=kth(1,1);
tot=dui[t1]; data[tot]=t1; cnt[tot]=1; father[tot]=t2; son[t2][1]=tot; cnt[t2]++;
} else
if (s[0]=='B'){
del(t1);
t2=kth(1,2);
tot=dui[t1]; data[tot]=t1; cnt[tot]=1; father[tot]=t2; son[t2][2]=tot; cnt[t2]++;
} else {
scanf("%d",&z);
if (z==0) continue;
if (z==-1) {
x=search(root,t1);
y=son[root][1];
while (son[y][2]) y=son[y][2];
} else
if (z==1) {
x=search(root,t1);
y=son[root][2];
while (son[y][1]) y=son[y][1];
}
if (y==0) continue;
t1=dui[data[x]]; dui[data[x]]=dui[data[y]]; dui[data[y]]=t1;
t1=data[x]; data[x]=data[y]; data[y]=t1;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: