zoukankan      html  css  js  c++  java
  • 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;
    }



  • 相关阅读:
    匿名对象、栈空间和堆空间,String的两种实例化方式的比较,"=="和"equals()"的区别
    间接调用父类私有成员方法、通过抽象类可以达到不需要实现接口所有方法的目的
    this关键字、构造快和静态块
    java可变参数的支持和foreach输出
    java-循环结构体
    switch和if else的区别和应用
    作用域对象
    JavaWeb1
    JavaScript 表单编程
    好久不见
  • 原文地址:https://www.cnblogs.com/yuecxl/p/2429332.html
Copyright © 2011-2022 走看看