多做题还是有好处的,这次终于了解了Splay()函数的情况,不然下次就要吃大亏了。。。。
但是还是不会处理将点删除的情况,所以只能再去多做做题目了。
![](http://www.sinaimg.cn/uc/myshow/blog/misc/gif/E___6706EN00SIGG.gif)
当时看胡浩大牛那边说要删点,但是删了好久都不会来,所以只能弱弱的不删点水掉这题了。。。
附上代码:
#include
#include
#include
using namespace std;
#define Maxn 250000
#define keyTree (edge[edge[root].ch[1]].ch[0])
//keytree是要 求的区间[a,b]
#pragma comment(linker, "/STACK:102400000,102400000")
struct Node {
int ch[2], pre, sz;
int rev, val;
//ch[root][0]表示root的左儿子地址,ch[root][1]表示root的右儿子地址
//pre[root]表示root的父亲
//sz[root]表示他和他儿子的个数,这颗子树的大小
//val[root]表示这个节点的值
} edge[Maxn];
int root, id;
int a[Maxn];
int link[Maxn];
struct node {
int no, h;
} cg[Maxn];
void Swap(int &x, int &y) {
int t = x;
x = y;
y = t;
}
void push_up(int x) {//延迟向上更新
edge[x].sz = 1 + edge[edge[x].ch[0]].sz + edge[edge[x].ch[1]].sz;
}
void push_down(int x) {//延迟向下更新 x是当前节点的内存块
if (edge[x].rev) {
Swap(edge[x].ch[0], edge[x].ch[1]);
edge[edge[x].ch[0]].rev ^= 1;
edge[edge[x].ch[1]].rev ^= 1;
edge[x].rev = 0;
}
}
void Rotate(int x, int f) {
int y = edge[x].pre;
push_down(y);
push_down(x);
edge[y].ch[!f] = edge[x].ch[f];
edge[edge[x].ch[f]].pre = y;
edge[x].pre = edge[y].pre;
if (edge[y].pre) {
edge[edge[y].pre].ch[edge[edge[y].pre].ch[1] == y] = x;
}
edge[x].ch[f] = y;
edge[y].pre = x;
push_up(y);
}
void Splay(int x, int goal) {//Splay直接往上找,所以直接使用Splay必须先push_down()来更新父节点
while (edge[x].pre != goal) {
int y = edge[x].pre, z = edge[y].pre;
push_down(z);
push_down(y);
push_down(x);
if (edge[edge[x].pre].pre == goal) {
Rotate(x, edge[edge[x].pre].ch[0] == x);
} else {
int f = (edge[z].ch[0] == y);
if (edge[y].ch[f] == x) {
Rotate(x, !f), Rotate(x, f);
} else {
Rotate(y, f), Rotate(x, f);
}
}
}
push_up(x);
if (goal == 0)root = x;
}
void RotateTo(int k, int goal) {//找第k个数,并把它旋转到goal下面
int x = root;
push_down(x);
while (edge[edge[x].ch[0]].sz != k) {
if (k < edge[edge[x].ch[0]].sz) {
x = edge[x].ch[0];
} else {
k -= (edge[edge[x].ch[0]].sz + 1);
x = edge[x].ch[1];
}
push_down(x);
}
Splay(x, goal);
}
void NewNode(int &x, int c, int fa) {//新建一个节点
x = ++id;
edge[x].ch[0] = edge[x].ch[1] = 0;
edge[x].pre = fa;
edge[x].sz = 1;
edge[x].rev = 0;
edge[x].val = c;
if (c >= 0) {
link[c] = x;
}
}
void MakeTree(int &x, int L, int R, int fa) {//x表示当前节点,建这颗平衡树
if (L > R)return;
int mid = (L + R) >> 1;
NewNode(x, a[mid], fa);
MakeTree(edge[x].ch[0], L, mid - 1, x);
MakeTree(edge[x].ch[1], mid + 1, R, x);
push_up(x); //把两个儿子凑起来
}
void Init(int n) {//
root = id = 0;
NewNode(root, -1, 0);
NewNode(edge[root].ch[1], -1, root);
MakeTree(keyTree, 1, n, edge[root].ch[1]);
push_up(edge[root].ch[1]);
push_up(root);
}
void Insert(int L, int R, int x) {//在L-R之间插入一个数
RotateTo(L, 0);
RotateTo(R, root);
NewNode(keyTree, x, edge[root].ch[1]);
push_up(edge[root].ch[1]);
push_up(root);
}
void Delete(int L, int R) {//删掉[L+1,R-1]
RotateTo(L, 0);
RotateTo(R, root);
keyTree = 0;
push_up(edge[root].ch[1]);
push_up(root);
}
int Get_Max(int r) {
push_down(r);
while (edge[r].ch[1]) {
r = edge[r].ch[1];
push_down(r);
}
return r;
}
void Del_root() {
if (edge[root].ch[0] == 0) {
root = edge[root].ch[1];
edge[root].pre = 0;
} else {
int m = Get_Max(edge[root].ch[0]);
Splay(m, root);
edge[m].ch[1] = edge[root].ch[1];
edge[edge[root].ch[1]].pre = m;
root = m;
edge[root].pre = 0;
push_up(root);
}
}
bool cmp(node x, node y) {
if (x.h == y.h) return x.no < y.no;
return x.h < y.h;
}
bool first = true;
void InOrder(int x) {//中序遍历所有的点
if (x) {
push_down(x);
InOrder(edge[x].ch[0]);
if (!first)printf(" ");
first = false;
printf("%d", edge[x].val);
InOrder(edge[x].ch[1]);
}
}
int main() {
int i, j, n;
while (scanf("%d", &n) != EOF) {
if (n == 0) break;
for (i = 0; i < n; i++) {
scanf("%d", &cg[i].h);
cg[i].no = i + 1;
}
sort(cg, cg + n, cmp);
for (i = 0; i < n; i++) {
a[cg[i].no] = i + 1;
}
Init(n);
for (i = 1; i < n; i++) {
int weizhi = link[i];
Splay(weizhi, 0);
int index = edge[edge[root].ch[0]].sz;
cout << edge[edge[root].ch[0]].sz << " ";
push_up(root);
RotateTo(i - 1, 0);
RotateTo(index + 1, root);
edge[keyTree].rev ^= 1;
}
cout << n << endl;
}
return 0;
}