OI模板 平衡树
普通平衡树-FHQ Treap
const int N = 500010;
int ch[N][2], val[N], pri[N], siz[N], tot;
int root, x, y, z;
void update(int x){
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
int newnode(int v){
siz[++tot] = 1;
val[tot] = v;
pri[tot] = rand();
return tot;
}
void init(){
srand(time(NULL));
tot = root = x = y = z = 0;
memset(ch, 0, sizeof(ch));
memset(val, 0, sizeof(val));
memset(pri, 0, sizeof(pri));
memset(siz, 0, sizeof(siz));
newnode(0xcfcfcfcf);
newnode(0x3f3f3f3f);
}
int merge(int x, int y){
if(!x || !y){
return x + y;
}
if(pri[x] < pri[y]){
ch[x][1] = merge(ch[x][1], y);
update(x);
return x;
} else {
ch[y][0] = merge(x, ch[y][0]);
update(y);
return y;
}
}
void split(int p, int k, int &x, int &y){
if(!p){
x = y = 0;
return;
}
if(val[p] <= k){
x = p;
split(ch[p][1], k, ch[p][1], y);
} else {
y = p;
split(ch[p][0], k, x, ch[p][0]);
}
update(p);
}
int kth(int p, int k){
while(true){
if(k <= siz[ch[p][0]]){
p = ch[p][0];
} else if(k == siz[ch[p][0]] + 1){
return p;
} else {
k -= siz[ch[p][0]] + 1;
p = ch[p][1];
}
}
}
void ins(int k){
split(root, k, x, y);
root = merge(merge(x, newnode(k)), y);
}
void del(int k){
split(root, k, x, z);
split(x, k-1, x, y);
y = merge(ch[y][0], ch[y][1]);
root = merge(merge(x, y), z);
}
int getrank(int k){
split(root, k-1, x, y);
int ans = siz[x] + 1;
root = merge(x, y);
return ans;
}
int getval(int k){
return val[kth(root, k)];
}
int getpre(int k){
split(root, k-1, x, y);
int ans = val[kth(x, siz[x])];
root = merge(x, y);
return ans;
}
int getnxt(int k){
split(root, k, x, y);
int ans = val[kth(y, 1)];
root = merge(x, y);
return ans;
}
void solve(){
init();
int n = rdi;
while(n--){
int op = rdi;
int k = rdi;
if(op == 1){
ins(k);
} else if(op == 2){
del(k);
} else if(op == 3){
writen(getrank(k));
} else if(op == 4){
writen(getval(k));
} else if(op == 5){
writen(getpre(k));
} else {
writen(getnxt(k));
}
}
}
FHQ-Treap:区间操作-区间翻转(文艺平衡树)
const int N = 500010;
int ch[N][2], val[N], pri[N], siz[N], rev[N], tot;
int root, x, y, z, n, m;
void update(int x){
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
int newnode(int v){
siz[++tot] = 1;
val[tot] = v;
pri[tot] = rand();
return tot;
}
void spread(int x){
swap(ch[x][0], ch[x][1]);
if(ch[x][0]){
rev[ch[x][0]] ^= 1;
}
if(ch[x][1]){
rev[ch[x][1]] ^= 1;
}
rev[x] = 0;
}
int merge(int x, int y){
if(!x || !y){
return x + y;
}
if(pri[x] < pri[y]){
if(rev[x]){
spread(x);
}
ch[x][1] = merge(ch[x][1], y);
update(x);
return x;
} else {
if(rev[y]){
spread(y);
}
ch[y][0] = merge(x, ch[y][0]);
update(y);
return y;
}
}
void split(int p, int k, int &x, int &y){
if(!p){
x = y = 0;
return;
}
if(rev[p]){
spread(p);
}
if(siz[ch[p][0]] + 1 <= k){
x = p;
split(ch[p][1], k-siz[ch[p][0]]-1, ch[p][1], y);
} else {
y = p;
split(ch[p][0], k, x, ch[p][0]);
}
update(p);
}
void init(){
srand(time(NULL));
tot = root = x = y = z = 0;
memset(ch, 0, sizeof(ch));
memset(val, 0, sizeof(val));
memset(pri, 0, sizeof(pri));
memset(siz, 0, sizeof(siz));
memset(rev, 0, sizeof(rev));
newnode(0xcfcfcfcf);
newnode(0x3f3f3f3f);
for(int i = 1; i <= n; ++ i){
root = merge(root, newnode(i));
}
}
void reverse(int l, int r){
split(root, l-1, x, y);
split(y, r-l+1, y, z);
rev[y] ^= 1;
root = merge(x, merge(y, z));
}
void print(int p){
if(!p){
return;
}
if(rev[p]){
spread(p);
}
print(ch[p][0]);
write(val[p]);
print(ch[p][1]);
}
void solve(){
n = rdi;
m = rdi;
init();
while(m--){
int l = rdi;
int r = rdi;
reverse(l, r);
}
print(root);
}