poj3580 SuperMemo

哇, 先感慨下, 无限长的代码。

这题只是一个模板的伸展树。 但是要想理解好这个伸展树, 还得要努力写的。

这里设了一个空指针null 当然咯, 这不是真正的空指针。

初始化的时候, 添加连个队列的头和队列的尾。

建伸展树的时候, 用堆建树。 

下面的几个函数都用到了线段树的思想。

select 函数, 是kth移动到point 的下方。要注意的一个细节就是 count = p->ch[0]->size; 这个是指向p 的左孩子.

在区间加某个数值。应该说是 把该区间移到某个节点的树叶下。 

reverse 函数, 这个函数, 只要把要旋转的区间进行旋转就可以了。 当然咯, 也是把要旋转的区间置于某个节点的叶子下面。

revolve 函数, 这个函数,要把旋转区间的左边和右边分别置于root 左孩子的右子树下,和root 右孩子的左孩子下方, 这时,将root->ch[0]->ch[1] 移到root->ch[1]->ch[0]->ch[1] 这里就可以咯

删除某个节点。 只是把要删除的节点升至根节点。然后进行删除。 把右孩子的最左孩子作为根, 或者左孩子的最右孩子作为根

插入某个节点在point, 可以把先前的point 移到根节点, 然后对point 后面的节点移到右节点, 这时我们就可以知道了, root->ch[1]->ch[0] 这时, 肯定是空的。 我们只要把要插入的节点插入这里就可以咯

获取最小值的话, 取出这个区间, 然后直接读取该区间的顶节点就可以了

ac

View Code
#include<stdio.h>
#include<string.h>
#define maxn 200008
#define inf 0x7ffffff

int min(int a, int b)
{
return a > b? b:a;
}
struct node
{
int val, mval, size, key, rev;

node *ch[2], *parent;

void add(int x)
{
if (size == 0)
{
return;
}
val += x;
mval += x;
key += x;
}

void reverse()
{
if (size == 0)
{
return ;
}

rev ^= 1;
node *mid = ch[0];
ch[0] = ch[1];
ch[1] = mid;
return;
}

void push_down()
{
if (size == 0)
{
return;
}
if (rev > 0)
{
ch[0]->reverse();
ch[1]->reverse();
}
if (key > 0)
{
ch[0]->add(key);
ch[1]->add(key);
}
rev = 0;
key = 0;
}

void update()
{
if (size == 0)
{
return;
}
size = ch[0]->size + ch[1]->size + 1;
mval = min(val, min(ch[0]->mval, ch[1]->mval));
return;
}
};

int arr[maxn];

class Splay
{
int top, cur;
node *stack[maxn], map[maxn];
public:
node *null, *root;

node *newNode(int x)
{
node *p;
if (top > 0)
{
p = stack[--top];
}
else
{
p = &map[cur ++];
}

p->key = 0;
p->ch[1] = p->ch[0] = p->parent = null;
p->mval = p->val = x;
p->size = 1;
p->rev = 0;
return p;
}

void init()
{
top = 0;
cur = 0;
null = newNode(inf);
null->size = 0;
root = newNode(inf);
null->ch[1] = root;
root->parent = null;
root->ch[1] = newNode(inf);
root->ch[1]->parent = root;
root->update();
}

node *build(int left, int right)
{
if (left > right)
{
return null;
}
int mid = (left + right) >> 1;
node *p = newNode(arr[mid]);
p->ch[0] = build(left, mid - 1);
p->ch[1] = build(mid + 1, right);
if (p->ch[0] != null)
{
p->ch[0]->parent = p;
}
if (p->ch[1] != null)
{
p->ch[1]->parent = p;
}
p->update();
return p;
}

void route(node *x, int c)
{
node *y = x->parent;
y->push_down();
x->push_down();

y->ch[c] = x->ch[!c];
if (null != x->ch[!c])
{
x->ch[!c]->parent = y;
}

x->parent = y->parent;
x->ch[!c] = y;

if (y->parent != null)
{
y->parent->ch[y->parent->ch[1] == y] = x;
}
y->parent = x;
y->update();
if (root == y)
{
root = x;
}
return;
}

void splay(node *x, node *p)
{
int c;
node *f, *l;

x->push_down();
while (x->parent != p)
{
l = x->parent;
if (l->parent == p)
{
route(x, x == l->ch[1]);
break;
}
f = l->parent;
if (l == f->ch[0])
{
if (x == l->ch[0])
{
route(l, 0);
route(x, 0);
}
else
{
route(x, 1);
route(x, 0);
}
}
else
{
if (x == l->ch[1])
{
route(l, 1);
route(x, 1);
}
else
{
route(x, 0);
route(x, 1);
}
}
}
x->update();
return;
}

void select(node *point, int kth)
{
int count;
node *p = root;

while (true)
{
p->push_down();
count = p->ch[0]->size;
if (count == kth)
{
break;
}
else if (count < kth)
{
kth -= count + 1;
p = p->ch[1];
}
else
{
p = p->ch[0];
}
}
splay(p, point);
return;
}

void add(int left, int right, int val)
{
select(null, left - 1);
select(root, right + 1);
node *p = root;
p->ch[1]->ch[0]->add(val);
splay(p, null);
return;
}

void reverse(int left, int right)
{
select(null, left - 1);
select(root, right + 1);
root->ch[1]->ch[0]->reverse();
return;
}

void revolve(int left, int right, int count)
{
int len = (right - left + 1);
count = ((count % len) + len) % len;

if (count == 0)
{
return;
} if (count == 1) {
del(right);
insert(left - 1, stack[top - 1]->val);
}
else
{
select(null, right - count + 1);
select(root, right + 1);
select(root, left - 1);
select(root->ch[1], right);

node *p = root->ch[0]->ch[1];
root->ch[0]->ch[1] = null;
root->ch[0]->update();
root->ch[1]->ch[0]->ch[1] = p;
p->parent = root->ch[1]->ch[0];
root->ch[1]->ch[0]->update();
splay(p, null);
}
return;
}

void del(int point)
{
int x;
select(null, point);
root->push_down();
node *oldroot = root;
root = root->ch[1];
root->parent = null;
select(null, 0);
root->ch[0] = oldroot->ch[0];
root->ch[0]->parent = root;
root->update();
stack[top ++] = oldroot;
return ;
}

void insert(int point, int val)
{
select(null, point);
select(root, point + 1);
node *p = newNode(val);
root->ch[1]->ch[0] = p;
p->parent = root->ch[1];
root->ch[1]->update();
splay(p, null);
}

int getMin(int left, int right)
{
select(null, left - 1);
select(root, right + 1);
return root->ch[1]->ch[0]->mval;
}
/*
void vis(node *t)
{
if (t == null)
{
return;
}
vis(t->ch[0]);
printf("%d %d %d\n", t->val, t->mval, t->size);
vis(t->ch[1]);
}
*/

}spt;

int main()
{
int n;

while (scanf("%d", &n) != EOF)
{
for (int i = 1; i <= n; i ++)
{
scanf("%d", &arr[i]);
}
spt.init();
if (n > 0)
{
node * p = spt.build(1, n);
spt.root->ch[1]->ch[0] = p;
p->parent = spt.root->ch[1];
spt.root->ch[1]->update();
spt.splay(p, spt.null);
}

int q, x, y, d;
scanf("%d", &q);
char cmd[10];
while (q --)
{
scanf("%s", cmd);
if (cmd[0] == 'A')
{
scanf("%d%d%d", &x, &y, &d);
spt.add(x, y, d);
}
else if (cmd[0] == 'I')
{
scanf("%d%d", &x, &y);
spt.insert(x, y);
}
else if (cmd[0] == 'D')
{
scanf("%d", &x);
spt.del(x);
}
else if (cmd[0] == 'M')
{
scanf("%d%d", &x, &y);
printf("%d\n", spt.getMin(x, y));
}
else if (cmd[3] == 'O')
{
scanf("%d%d%d", &x, &y, &d);
spt.revolve(x, y , d);
}
else
{
scanf("%d%d", &x, &y);
spt.reverse(x, y);
}
}
}
return 0;
}



posted @ 2012-04-01 20:49  xiaoln  阅读(478)  评论(0编辑  收藏  举报