splay的区间操作(区间反转)
由于splay表示的是区间,对于重复元素的查找可能会出错(只是splay的实现导致的,没有办法)
离散化那个地方有点小技巧,主要是针对数据的重复性,也就是去重。
我这里有对这个问题的小结:http://hlq07.sinaapp.com/archives/15/
#include<bits/stdc++.h>
using namespace std;
struct node {
int key, size, Min;
bool sig;
node *c[2];
node():key(0), size(0), Min(INT_MAX) { c[0] = c[1] = this; }
node(int key, node *c0, node *c1):key(key), sig(0) { c[0] = c0, c[1] = c1; }
node *rz() { return size = c[0]->size + c[1]->size + 1, Min = min(key, min(c[0]->Min, c[1]->Min)), this; }
void push_down() {
if(!sig) return ;
sig ^= 1, c[0]->sig ^= 1, c[1]->sig ^= 1;
swap(c[0], c[1]);
}
} Tnull, *null = &Tnull;
struct splay {
node *root;
void zig(bool d) {
node *t = root->c[d];
root->c[d] = null->c[d];
null->c[d] = root;
root = t;
}
void zigzig(bool d) {
node *t = root->c[d]->c[d];
root->c[d]->c[d] = null->c[d];
null->c[d] = root->c[d];
root->c[d] = null->c[d]->c[!d];
null->c[d]->c[!d] = root->rz();
root = t;
}
void finish(bool d) {
node *t = null->c[d], *p = root->c[!d];
while(t != null) {
t = null->c[d]->c[d];
null->c[d]->c[d] = p;
p = null->c[d]->rz();
null->c[d] = t;
}
root->c[!d] = p;
}
void select(int k) {
int t;
while(1) {
root->push_down();
bool d = k > (t = root->c[0]->size);
if(k == t || root->c[d] == null) break;
if(d) k -= t + 1;
root->c[d]->push_down();
bool dd = k > (t = root->c[d]->c[0]->size);
if(k == t || root->c[d]->c[dd] == null) {
zig(d);
break;
}
if(dd) k -= t + 1;
d != dd ? zig(d), zig(dd) : zigzig(d);
}
finish(0), finish(1);
root->rz();
}
void search_min() {
while(1) {
root->push_down();
bool d = root->Min < root->c[0]->Min;
if(root->c[d] == null || root->Min == root->key) break; //适应题目需要加上 "x == root->key",删去x > root->key的判断
root->c[d]->push_down();
bool dd = root->c[d]->Min < root->c[d]->c[0]->Min;
if(root->c[d]->c[dd] == null || root->c[d]->Min == root->c[d]->key) {
zig(d);
break;
}
d != dd ? zig(d), zig(dd) : zigzig(d);
}
finish(0), finish(1);
root->rz();
}
void del_min() {
search_min();
node *oldroot = root;
root = oldroot->c[1];
select(0);
root->c[0] = oldroot->c[0];
root->rz();
root->c[0]->sig ^= 1;
delete oldroot;
}
} sp;
node *Build(int *st, int *ed) {
if(st == ed) return null;
int *mid = st + (ed - st) / 2;
return (new node(*mid, Build(st, mid), Build(mid + 1, ed)))->rz();
}
const int MAXN = 100000;
int n, A[MAXN + 10], tmp[MAXN + 10];
int cnt[MAXN + 10];
int main() {
int i;
scanf("%d", &n);
for(i = 1; i <= n; i++) {
scanf("%d", &A[i]);
tmp[i] = A[i];
}
sort(tmp + 1, tmp + 1 + n);
for(i = 1; i <= n; i++) {
int t = lower_bound(tmp + 1, tmp + 1 + n, A[i]) - tmp;
A[i] = t + cnt[t];
cnt[t]++;
}
A[n + 1] = INT_MAX;
sp.root = Build(A + 1, A + n + 2);
for(i = 1; i <= n; i++) {
sp.del_min();
printf(i == n ? "%d\n" : "%d ", sp.root->c[0]->size + i);
}
return 0;
}