题目描述见链接 .
使用维护
Input: 依次插入节点, 不断 初始插入 到上个节点的右子树中
Top : 将权值为的点 删去 , 再插入作为到的最左边儿子的左儿子
Bottom : 将权值为的点 删去 , 在插入作为的最右边儿子的右儿子
Insert : 将权值为的点 删去 , 设删去的点等级为, 将等级为的点到根节点, 把点 插入之间 根节点 (不要在意语序…)
Ask : 直接将节点到根节点, 输出左子树大小即可
Query : 查询第大的元素
初始插入 : 不断将当前节点插入到 上个插入节点 的右子树即可, 不要忘记Splay到根节点
删去 : 直接前缀后缀删除法即可
插入之间 : 将该节点的未来的右儿子置为该节点, 该节点的右儿子置为原来的右儿子
初始化序列 时不断将第 个元素插入作为第 个元素的右子树 .
- 操作: 直接将 元素旋转到根节点, 将其左子树变为 的后继 的左儿子 .
- 操作: 直接将 元素旋转到根节点, 将其右子树变为 的前驱 的右儿子 .
- 操作: 直接将 元素 与其 前驱/后继 的信息 进行交换即可 .
- 操作: 直接将 旋转到根, 输出其左子树大小即可 .
- 操作: 查询第 大即可 .
- 注意 时 的赋值顺序 .
- 交换时交换的是位置, 不是值, 只要将相关映射和对应位置上的值交换即可 .
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 80005;
int N;
int M;
int Mp[maxn];
char Smp[10];
namespace BBT{
int rot;
int node_cnt;
struct Node{ int v, fa, son[2], size; } T[maxn];
bool chk(int x){ return T[T[x].fa].son[0] != x; }
void rotate(int x){
int y = T[x].fa, z = T[y].fa;
int dir = chk(x), sn = T[x].son[dir^1];
if(y == rot) rot = x;
else T[z].son[chk(y)] = x; T[x].fa = z;
T[y].son[dir] = sn, T[sn].fa = y;
T[x].son[dir^1] = y, T[y].fa = x;
T[y].size = T[T[y].son[0]].size + T[T[y].son[1]].size + 1;
T[x].size = T[T[x].son[0]].size + T[T[x].son[1]].size + 1;
}
void Splay(int x, int aim=0){
while(T[x].fa != aim){
int y = T[x].fa, z = T[y].fa;
if(z != aim){
if(chk(x) == chk(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
int Kth(int k, int aim){
int ls = T[k].son[0];
if(T[ls].size + 1 == aim) return k;
else if(T[ls].size >= aim) return Kth(ls, aim);
return Kth(T[k].son[1], aim - T[ls].size - 1);
}
void Add_node(int x){
Mp[x] = ++ node_cnt, T[node_cnt] = (Node){ x, 0, {0,0}, 1 };
if(node_cnt > 1){
T[node_cnt-1].son[1] = node_cnt, T[node_cnt].fa = node_cnt - 1;
Splay(node_cnt);
}
}
void Top(int k){
Splay(k);
if(!T[k].son[0]) return ;
else if(!T[k].son[1]){ T[k].son[1] = T[k].son[0], T[k].son[0] = 0; return ; }
int ls = T[k].son[0];
int y = Kth(rot, T[ls].size+2);
T[y].son[0] = ls, T[ls].fa = y, T[k].son[0] = 0;
Splay(y);
}
void Bottom(int k){
Splay(k);
if(!T[k].son[1]) return ;
else if(!T[k].son[0]){ T[k].son[0] = T[k].son[1], T[k].son[1] = 0; return ; }
int ls = T[k].son[0], rs = T[k].son[1];
int y = Kth(rot, T[ls].size);
T[y].son[1] = rs, T[rs].fa = y, T[k].son[1] = 0;
Splay(y);
}
void Insert(int k, int opt){
if(!opt) return ;
Splay(k);
int rk = T[T[k].son[0]].size + 1, y = Kth(rot, rk + opt);
std::swap(Mp[T[k].v], Mp[T[y].v]);
std::swap(T[k].v, T[y].v);
}
void Ask(int k){ Splay(k); printf("%d
", T[T[k].son[0]].size); }
void Query(int rk){ int y = Kth(rot, rk); printf("%d
", T[y].v); }
}
void Work(){
scanf("%s", Smp);
int x = read();
if(Smp[0] == 'T') BBT::Top(Mp[x]);
else if(Smp[0] == 'B') BBT::Bottom(Mp[x]);
else if(Smp[0] == 'I') BBT::Insert(Mp[x], read());
else if(Smp[0] == 'A') BBT::Ask(Mp[x]);
else BBT::Query(x);
}
int main(){
N = read(), M = read();
BBT::rot = 1;
for(reg int i = 1; i <= N; i ++) BBT::Add_node(read());
while(M --) Work();
return 0;
}