poj 3580 SuperMemo(Splay)

               基本包括了Splay Tree的所有操作,插入,删除,右移,翻转,区间更新,区间查询。学习Splay Tree推荐一个博客,FZU_Jason。这道题基本上就是抄的他的。。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define CLR(a, b) memset(a, b, memset(a))
using namespace std;
const int N = 200010;
const int INF = 0x7FFFFFFF;

struct SplayTree
{
    int size, root, top;
    int st[N], a[N];
    int ch[N][2], pre[N], key[N], num[N];
    //num 当前根下节点个数
    int add[N], mini[N];
    bool flip[N];
    inline void PushUp(int x)
    {
        num[x] = num[ch[x][0]] + num[ch[x][1]] + 1;
        mini[x] = min(mini[ch[x][0]], mini[ch[x][1]]);
        mini[x] = min(mini[x], key[x]);
    }
    inline void PushDown(int x)
    {
        int L, R;
        L = ch[x][0];R = ch[x][1];
        if(add[x])
        {
            if(L)
            {
                add[L] += add[x];
                key[L] += add[x];
                mini[L] += add[x];
            }
            if(R)
            {
                add[R] += add[x];
                key[R] += add[x];
                mini[R] += add[x];
            }
            add[x] = 0;
        }
        if(flip[x])
        {
            flip[L] ^= true;
            flip[R] ^= true;
            swap(ch[x][0], ch[x][1]);
            flip[x] = false;
        }
    }
    void NewNode(int &x, int father, int val)
    {
        if(top != -1)
            x = st[top --];
        else
            x = ++size;
        ch[x][0] = ch[x][1] = add[x] = 0;
        pre[x] = father;
        key[x] = mini[x] = val;
        num[x] = 1;
        flip[x] = false;
    }
    void Build(int &x, int L, int R, int father)
    {
        if(L <= R)
        {
            int mid = (L + R) >> 1;
            NewNode(x, father, a[mid]);
            Build(ch[x][0], L, mid - 1, x);
            Build(ch[x][1], mid + 1, R, x);
            PushUp(x);
        }
    }
    void Init(int n)
    {
        root = size = 0;
        top = -1;
        flip[0] = false;
        ch[0][0] = ch[0][1] = pre[0] = num[0] = add[0] = 0;
        key[0] = mini[0] = INF;
        NewNode(root, 0, INF);
        NewNode(ch[root][1], root, INF);
        Build(ch[ch[root][1]][0], 1, n, ch[root][1]);
        PushUp(ch[root][1]);
        PushUp(root);
    }
    void Rotate(int x, int kind)
    {
        int y = pre[x];
        PushDown(x);
        ch[y][!kind] = ch[x][kind];
        pre[ch[x][kind]] = y;
        if(pre[y])
            ch[pre[y]][ch[pre[y]][1] == y] = x;
        pre[x] = pre[y];
        ch[x][kind] = y;
        pre[y] = x;
        PushUp(y);
    }
    void Splay(int r, int goal)
    {
        while(pre[r] != goal)
        {
            if(pre[pre[r]] == goal) Rotate(r, ch[pre[r]][0] == r);
            else
            {
                int y = pre[r];
                int kind = ch[pre[y]][0] == y;
                if(ch[y][kind] == r)
                    Rotate(r, !kind), Rotate(r, kind);
                else
                    Rotate(y, kind), Rotate(r, kind);
            }
        }
        //PushUp(r);
        if(goal == 0) root = r;
    }
    /*
    void Rotate(int x, int kind) {
        int y, z;
        y = pre[x];
        z = pre[y];
        PushDown(y);
        ch[y][!kind] = ch[x][kind];
        pre[ch[x][kind]] = y;
        ch[z][ch[z][1] == y] = x;
        pre[x] = z;
        ch[x][kind] = y;
        pre[y] = x;
        PushUp(y);
    }
    void Splay(int x, int goal) {
        if (x != goal) {
            PushDown(x);
            while (pre[x] != goal) {
                if (ch[pre[x]][0] == x)
                    Rotate(x, 1);
                else
                    Rotate(x, 0);
            }
            PushUp(x);
            if (!goal)
                root = x;
        }
    }
    */
    int Select(int k)
    {
        int x;
        PushDown(root);
        for(x = root; num[ch[x][0]] + 1 != k;)
        {
            if(num[ch[x][0]] + 1 > k)
                x = ch[x][0];
            else
                k -= num[ch[x][0]] + 1, x = ch[x][1];
            PushDown(x);
        }
        return x;
    }
    void Add(int x, int y, int val)
    {
        int t;
        x = Select(x - 1);
        y = Select(y + 1);
        Splay(x, 0);
        Splay(y, x);
        t = ch[y][0];
        add[t] += val;
        key[t] += val;
        mini[t] += val;
        PushUp(y);
        PushUp(x);
    }
    void Flip(int x, int y)
    {
        x = Select(x - 1);
        y = Select(y + 1);
        Splay(x, 0);
        Splay(y, x);
        flip[ch[y][0]] ^= true;
    }
    void Revolve(int x, int y, int t)
    {
        int cnt = y - x + 1;
        t %= cnt;
        if(t < 0)
            t += cnt;
        if(t)
        {
            Flip(x, y - t);
            Flip(y - t + 1, y);
            Flip(x, y);
        }
    }
    void Insert(int x, int val)
    {
        int a, b;
        a = Select(x);
        b = Select(x + 1);
        Splay(a, 0);
        Splay(b, a);
        NewNode(ch[b][0], b, val);
        PushUp(b);
        PushUp(a);
    }
    void Delete(int x)
    {
        int a, b;
        a = Select(x - 1);
        b = Select(x + 1);
        Splay(a, 0);
        Splay(b, a);
        st[++ top] = ch[b][0];
        ch[b][0] = 0;
        PushUp(b);
        PushUp(a);
    }
    int MIN(int x, int y)
    {
        x = Select(x - 1);
        y = Select(y + 1);
        Splay(x, 0);
        Splay(y, x);
        return mini[ch[y][0]];
    }
}spt;
int main() {
    char cmd[18];
    int n, q, i;
    int x, y, val;
    while (~scanf("%d", &n)) {
        for (i = 1; i <= n; i++)
            scanf("%d", &spt.a[i]);
        spt.Init(n);
        scanf("%d", &q);
        while (q--) {
            scanf(" %s", cmd);
            if (strcmp(cmd, "ADD") == 0) {
                scanf("%d%d%d", &x, &y, &val);
                spt.Add(x + 1, y + 1, val);
            } else if (strcmp(cmd, "REVERSE") == 0) {
                scanf("%d%d", &x, &y);
                spt.Flip(x + 1, y + 1);
            } else if (strcmp(cmd, "REVOLVE") == 0) {
                scanf("%d%d%d", &x, &y, &val);
                spt.Revolve(x + 1, y + 1, val);
            } else if (strcmp(cmd, "INSERT") == 0) {
                scanf("%d%d", &x, &val);
                spt.Insert(x + 1, val);
            } else if (strcmp(cmd, "DELETE") == 0) {
                scanf("%d", &x);
                spt.Delete(x + 1);
            } else {
                scanf("%d%d", &x, &y);
                printf("%d\n", spt.MIN(x + 1, y + 1));
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值