这道题我全网就看到了一个treap,QAQ
这道题有个难题,他每次是对一个编号的书进行操作,如果是对从左到右的一个排名的书进行操作还好办.....
因此在网上一位大神的代码帮助下,我发现,可以在外界对每一个书的编号搞一个指针,然后用get_rank函数来求出这本书的排名,然后就很好搞了。。。
get_rank 怎么写呢? 我们将当前节点往父亲爬,直到爬到根,如果当前节点是其父亲的右儿子,那么rank就加上父亲的左儿子的大小,再加上1(父亲的大小)
由于要往上爬,当然要记录父亲了,在update里维护一下就好。
上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<string>
#include<cstdlib>
#include<cmath>
#include<cctype>
const int N = 8e4 + 9;
struct Treap {
int id, size, hr;
Treap *l, *r, *fa;
Treap () {}
Treap (int id, Treap *fl) : id(id),size(1),hr(rand()),l(fl),r(fl),fa(fl) {}
void update () { size = l -> size + r -> size + 1; l -> fa = r -> fa = this; }
}*root, meme[N], *pool = meme, *Null;
Treap* newnode (int xxx) {
return new (pool++) Treap (xxx, Null);
}
using std :: pair;
typedef pair <Treap*,Treap*> Droot;
Droot Split (Treap *x,int k) {
if(x == Null) return Droot (Null, Null);
Droot y;
if(x -> l -> size >= k) {
y = Split (x -> l, k);
x -> l = y . second;
x -> update ();
y . second = x;
} else {
y = Split (x -> r, k - x -> l -> size - 1);
x -> r = y . first;
x -> update ();
y . first = x;
}
return y;
}
Treap* Merge (Treap *A,Treap *B) {
if(A == Null) return B;
if(B == Null) return A;
if(A -> hr > B -> hr) {
B -> l = Merge (A, B -> l);
B -> update ();
return B;
} else {
A -> r = Merge (A -> r, B);
A -> update ();
return A;
}
}
Treap *ptr[N];
int n,m,id[N];
Treap* Build () {
static Treap *stk[N], *last, *x; int top = 0;
for (int i = 1; i <= n; ++i) {
last = Null; ptr[id[i]] = x = newnode (id[i]);
while (top && x -> hr < stk[top] -> hr) {
stk[top] -> update ();
last = stk[top--];
}
if(top) stk[top] -> r = x,x -> fa = stk[top];
x -> l = last; last -> fa = x;
stk[++top] = x;
}
while (top) stk[top--] -> update ();
return stk[1];
}
int get_rank (Treap *x) { // 有了getrank我们就可以搞事情了....
int res = x -> l -> size;
while (x -> fa != Null) {
if (x == x -> fa -> r) res += x -> fa -> l -> size + 1;
x = x -> fa;
}
return res;
}
void puton (int xxx, bool v) {
static Droot clc1,clc2;
int k = get_rank (ptr[xxx]);
clc1 = Split (root, k); clc2 = Split (clc1.second,1);
if(v) root = Merge(Merge(clc2.first,clc1.first),clc2.second);
else root = Merge (clc1.first,Merge(clc2.second,clc2.first));
}
void bookon (int xxx,int opt) {
if(!opt) return ;
static Droot clc1,clc2,clc3;
int k = get_rank (ptr[xxx]);
clc1 = Split (root, k);
clc2 = Split (clc1.second, 1);
if(opt == -1) clc1 = Split(clc1.first, clc1.first -> size - 1), root = Merge (Merge(clc1.first,clc2.first),Merge(clc1.second,clc2.second));
else clc3 = Split(clc2.second, 1), root = Merge (Merge(clc1.first, clc3.first), Merge(clc2.first,clc3.second));
}
int getin () {
int num = 0; char a; bool fl = false;
for (a = getchar(); a < '0' || a > '9'; a = getchar()) if(a == '-') fl = true;
for (; a >= '0' && a <= '9'; a = getchar()) num = (num << 3) + (num << 1) + a - '0';
if(fl) num = -num;
return num;
}
int rank (Treap *x, int k) {
if (x -> l -> size >= k) return rank (x -> l, k);
if (x -> l -> size + 1 == k) return x -> id;
return rank (x -> r, k - x -> l -> size - 1);
}
char opt[23];
int x;
void Print (Treap *x) {
if(x == Null) return ;
Print (x -> l);
printf("%d\n",x -> id);
Print (x -> r);
}
bool it (Treap *xx) {
if(xx == Null) return 0;
bool ok = 0;
ok |= it (xx -> l);
ok |= it (xx -> r);
return ok || xx->fa==Null || xx->fa->l==xx || xx->fa->r==xx;
}
int main () {
freopen ("1514.in","r",stdin);
freopen ("1514.out","w",stdout);
Null = new Treap (); Null -> size = 0;
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; ++i) id[i] = getin ();
root = Build ();
for (int i = 1; i <= m; ++i) {
scanf("%s%d",opt,&x);
if(opt[0] == 'T') puton (x, true);
else if(opt[0] == 'B') puton (x, false);
else if(opt[0] == 'I') bookon (x, getin());
else if(opt[0] == 'A') printf ("%d\n",get_rank(ptr[x]));
else printf ("%d\n",rank(root, x));
}
return 0;
}
That is all.Thank you for watching.