作为一个刚学Treap只会打板子的菜鸡,这个做法还参悟题解了一节课才参悟出来的,感觉这个方法很巧妙
变量解释
A[i]表示编号为i的书的优先级,优先级第k小就是从上向下数第k本书
树的节点Node.val表示优先级,也是平衡树排序的关键字
Node.num表示该节点对应书的编号
因为没有两个书的优先级是一样的,所以元素不重复,getrank函数好写些
五个操作
Top:删去原来该书的代表元素,把该书优先级改为当前最小(置顶)
Bottom:删去原来该书的代表元素,把该书优先级改为当前最大(置底)
Insert:把该书与目标书代表的两个元素先从Treap中删掉,然后交换优先级,再加入Treap
Ask:对于编号为S的书,输出A[S]的名次-1
Query:输出优先级第S个节点的编号
样例很舒适地过了,然后交上去
卧槽十分?考场凉凉?
然后对拍发现自己Del函数有个地方忘Update了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls (T[rt].s[0])
#define rs (T[rt].s[1])
#define son (T[rt].s[d])
using namespace std;
int Num,Size,A[202020];
char ch[200];
struct Node{
int s[2],num,val,rnd,siz;
bool cmp(int x){
if (x<val) return 0;
return 1;
}
void NewNode(int x){
val=x; rnd=rand(); num=Num; siz=1;
}
}T[4002020];
bool Cmpson(int rt){
if (T[rs].rnd<T[ls].rnd) return 1;
return 0;
}
void update(int rt){
T[rt].siz=T[ls].siz+T[rs].siz+1;
}
void Rotate(int &rt,int d){
int t=T[rt].s[d];
T[rt].s[d]=T[t].s[d^1];
T[t].s[d^1]=rt;
update(rt); update(t);
rt=t;
}
void Insert(int &rt,int x){
if (!rt){
rt=++Size;
T[rt].NewNode(x);
return;
}
T[rt].siz++;
int d=T[rt].cmp(x);
Insert(son,x);
if (T[son].rnd<T[rt].rnd) Rotate(rt,d);
}
void Del(int &rt,int x){
int d;
if (T[rt].val==x){
if (ls*rs==0){
rt=ls+rs;
return;
}
d=Cmpson(rt);
Rotate(rt,d); Del(T[rt].s[d^1],x);
update(rt);//一遍交漏了这句
return;
}
d=T[rt].cmp(x);
Del(son,x);
update(rt);
}
int getrank(int rt,int x){
if (x==T[rt].val) return T[ls].siz+1;
if (T[rt].val>x) return getrank(ls,x);
else return T[ls].siz+1+getrank(rs,x);
}
int Find(int rt,int x){
if (T[ls].siz+1==x) return T[rt].num;
if (T[ls].siz>=x) return Find(ls,x);
else return Find(rs,x-T[ls].siz-1);
}
int main(){
int rank,x,n,m,Min=1,Max,i,rt=0,t;
scanf("%d %d",&n,&m);
Max=n;
for (i=1;i<=n;i++){
scanf("%d",&Num);
A[Num]=i;
Insert(rt,i);
}
while (m--){
cin>>ch;
int i;
scanf("%d",&Num);
if (ch[0]=='T'){
Del(rt,A[Num]);
A[Num]=--Min;
Insert(rt,A[Num]);
continue;
}
if (ch[0]=='B'){
Del(rt,A[Num]);
A[Num]=++Max;
Insert(rt,A[Num]);
continue;
}
if (ch[0]=='I'){
scanf("%d",&t);
if (!t) continue;
rank=getrank(rt,A[Num]);
x=Find(rt,rank+t);
Del(rt,A[Num]); Del(rt,A[x]);
swap(A[Num],A[x]);
Insert(rt,A[Num]);
Num=x; Insert(rt,A[Num]);
continue;
}
if (ch[0]=='A')
printf("%d\n",getrank(rt,A[Num])-1);
else
printf("%d\n",Find(rt,Num));
}
return 0;
}
//data1.in
/*8 8
1 2 3 4 5 6 7 8
I 4 -1
B 7
Q 7
A 6
T 4
A 3
B 5
T 4
*/
//6 6 3
//std:8 5 3