http://www.lydsy.com/JudgeOnline/problem.php?id=1861
写好关键的三个函数后就是水水的模拟题,旋转来旋转去的操作,so easy
有几点值得注意:
1:取出Splay中某个节点,然后在插回去,这个节点的左右儿子要记得清空
2:每次更改关系后别忘了up上去
没了。。
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef long long lld;
#define L x->c[0]
#define R x->c[1]
#define KT root->c[1]->c[0]
const int maxn = 111111;
struct node {
struct node *c[2], *fa;
int id;
int sz;
int val;
inline bool d() {
return fa->c[0] == this;
}
inline void setc(int d, node *s) {
c[d] = s;
s->fa = this;
}
inline void up() {
sz = c[0]->sz + c[1]->sz + 1;
}
inline void clear(node *null) {
c[0] = c[1] = null;
sz = 1;
}
} NODE[2 * maxn], *null = &NODE[0] ;
int top;
node* ID[maxn];
struct SplayTree {
node* root;
void Rotate(node *x,int f) {
node *y = x->fa;
y->setc(!f,x->c[f]);
x->fa = y->fa;
if (y->fa != null) y->fa->setc(!y->d(),x);
x->setc(f,y);
y->up();
}
void Splay(node *x, node *goal) {
while (x->fa != goal) {
if (x->fa->fa == goal)
Rotate(x, x->d());
else {
int f = x->fa->d();
x->d() == f ? Rotate(x->fa, f) : Rotate(x, !f);
Rotate(x, f);
}
}
x->up();
if (goal == null) root = x;
}
void RTO(int k, node *goal) {
if(k<1||k>root->sz) while(1);
node *x = root;
while (L->sz + 1 != k) {
if(k < L->sz + 1) x = L;
else {
k -= L->sz + 1;
x = R;
}
}
Splay(x, goal);
}
void build(node* &x,int l,int r,node *fa) {
if(l > r) return ;
int m = l + r >>1;
x = new_node(fa,num[m]);
build(x->c[0],l,m-1,x);
build(x->c[1],m+1,r,x);
x->up();
}
node *new_node(node *fa, int v) {
node *x = &NODE[++top];
x->id = top;
x->c[0] = x->c[1] = null;
x->sz = 1;
x->val = v;
x->fa = fa;
if(v!=-1) ID[v] = x;
return x;
}
void init(int n) {
for(int i = 1; i <= n; i++) scanf("%d",&num[i]);
root = new_node(null,-1);
build(root->c[1],1,n,root);
root->up();
}
void Del_root() { // delete the root
node* t = root;
if (t->c[1] != null) {
root = t->c[1];
RTO(1, null);
root->c[0] = t->c[0];
if (root->c[0] != null)
root->c[0]->fa = root;
} else
root = root->c[0];
root->fa = null;
if (root != null)
root->up();
}
void Insert(int p,int v) {
Splay(ID[p],null);
int NC = root->c[0]->sz - 1;
Del_root();
ID[p]->clear(null);
NC += v;
RTO(NC+1,null);
if(root->c[1] == null) {
root->setc(1,ID[p]);
root->up();
return ;
}
RTO(NC+2,root);
root->c[1]->setc(0,ID[p]); root->c[1]->up(); root->up();
}
void Bottom(int p) {
Splay(ID[p],null);
Del_root();
ID[p]->clear(null);
RTO(root->sz,null);
root->setc(1,ID[p]); root->up();
}
void Top(int p) {
Splay(ID[p],null);
Del_root();
ID[p]->clear(null);
RTO(1,null);
if(root->c[1] == null) {
root->setc(1,ID[p]);
return ;
}
RTO(2,root);
root->c[1]->setc(0,ID[p]); root->c[1]->up(); root->up();
}
int Query(int p) {
RTO(p+1,null);
return root->val;
}
int Ask(int p) {
Splay(ID[p],null);
return root->c[0]->sz - 1;
}
void vist(node *x) {
if (x != null) {
printf("节点:%2d : 左儿子: %2d 右儿子: %2d sz: %2d val: %d\n",
x->id,x->c[0]->id,x->c[1]->id,x->sz,x->val);
vist(x->c[0]);
vist(x->c[1]);
}
}
void debug() {
puts("************");
vist(root);
puts("\n*****************");
}
int num[maxn];
} spt;
void prepare() {
top = 0;
null->id = 0;
null->c[0] = null->c[1] = null->fa = NULL;
null->sz = 0;
null->val = 0;
}
int main() {
char op[10];
prepare();
int n , m , p;
scanf("%d%d",&n,&m);
spt.init(n);
while(m--) {
scanf("%s",op);
if(op[0] == 'Q') {
scanf("%d",&p);
printf("%d\n",spt.Query(p));
} else if(op[0] == 'A') {
scanf("%d",&p);
printf("%d\n",spt.Ask(p));
} else if(op[0] == 'B') {
scanf("%d",&p);
spt.Bottom(p);
} else if(op[0] == 'T') {
scanf("%d",&p);
spt.Top(p);
} else {
int v;
scanf("%d%d",&p,&v);
spt.Insert(p,v);
}
}
return 0;
}