题解 P2596 【[ZJOI2006]书架】
我的做法好像又是比较清奇
这显然是个文艺平衡树的题
看看每个操作我们要干什么
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本书的编号。
询问第
由于我的splay需要插入 INF 和 -INF 以便于求PRE和NXT的时候不会RE,所以某些地方需要 +1 -1的
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<iostream>
//#define debug
#define rg register
#define il inline
#define MX (100000 + 4)
#define INF (0x7f7f7f7f)
void swap(int &x ,int &y){
int t = x;
x = y ,y = t;
}
namespace SPLAY{
#define lch(x) ch[x][0]
#define rch(x) ch[x][1]
int root ,sz;
int ch[MX][2] ,fa[MX] ,mark[MX] ,size[MX] ,key[MX] ,pos[MX];
int get(int x){return x == ch[fa[x]][1];}
void pushup(int x){
if(!x) return;
size[x] = 1;
if(lch(x)) size[x] += size[lch(x)];
if(rch(x)) size[x] += size[rch(x)];
}
void reverse(int x){
if(!x) return ;
swap(lch(x) ,rch(x));
mark[x] ^= 1;
}
void pushdown(int x){
if(!x) return;
if(mark[x]){
if(lch(x)) reverse(lch(x));
if(rch(x)) reverse(rch(x));
mark[x] = false;
}
}
void rotate(int x){
int f = fa[x] ,gf = fa[f] ,which = get(x) ,w = ch[x][!which];
if(gf) ch[gf][ch[gf][1] == f] = x;
ch[x][!which] = f ,ch[f][which] = w;
if(w) fa[w] = f;
fa[f] = x ,fa[x] = gf;
pushup(f) ,pushup(x);
}
int stack[MX] ,dep;
void splay(int x ,int goal = 0){ //////
int f = x;
stack[++dep] = f;
while(f) stack[++dep] = f = fa[f];
while(dep) pushdown(stack[dep--]);
for( ; (f = fa[x]) != goal ; rotate(x)){
if(fa[f] != goal) rotate(get(x) == get(f) ? f : x);
}if(!goal) root = x;
}
void insert(int x){
int now = root;
while(rch(now)) now = rch(now);
fa[++sz] = now;
if(now) ch[now][1] = sz;
key[sz] = x;
size[sz] = 1;
mark[sz] = ch[sz][0] = ch[sz][1] = 0;
pushup(now);
splay(sz);
}
int rank(int val){
splay(pos[val]);
return size[lch(pos[val])] + 1;
}
int Kth(int rank){
int x = root;
while(true){
pushdown(x);
if(lch(x) && rank <= size[lch(x)]) x = lch(x);
else{
int tmp = (lch(x) ? size[lch(x)] : 0) + 1;
if(rank <= tmp) return x;
rank -= tmp;
x = rch(x);
}
}
}
void reverse(int l ,int r){
splay(l - 1);
if(l >= r) return;
int PRE = Kth(l - 1) ,NXT = Kth(r + 1);
splay(PRE);
splay(NXT ,PRE);
reverse(ch[NXT][0]);
}
}using namespace SPLAY;
int main(){
int n ,m;
scanf("%d%d" ,&n ,&m);
insert(-INF);
for(rg int i = 1 ,tmp ; i <= n ; ++i){
scanf("%d" ,&tmp);
pos[tmp] = i + 1;
insert(tmp);
}
insert(INF);
#ifdef debug
test();puts("");
#endif
char op[33];
for(rg int i = 1 ,s ,t ; i <= m ; ++i){
scanf("%s%d" ,op ,&s);
switch(op[0]){
case 'T':{
int l = rank(s);
if(l != 2){
reverse(2 ,l);
reverse(3 ,l);
}
break;
}
case 'B':{
int l = rank(s);
if(l != n + 1){
reverse(l ,n + 1);
reverse(l ,n);
}
break;
}
case 'I':{
int delta ,P = rank(s);
scanf("%d" ,&delta);
switch(delta){
case 0:{break;}
case 1:{
reverse(P ,P + 1);
break;
}
case -1:{
reverse(P - 1 ,P);
break;
}
}
break;
}
case 'A':{
printf("%d \n" ,rank(s) - 2);
break;
}
case 'Q':{
printf("%d \n" ,key[Kth(s + 1)]);
break;
}
}
}return 0;
}