【HDU 4453】 Looploop(Splay)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define keytree (ch[ ch[root][1] ][0])
using namespace std;
const int SIZEN = 210005;
struct SplayTree{
    int ch[SIZEN][2];
    int sz[SIZEN];
    int pre[SIZEN];
    int top,root;
    int k1,k2,n,cnt;

    inline void change(int x){
        swap(ch[x][0],ch[x][1]);
    }
    inline void pushup(int x){
        sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
    }
    inline void pushdown(int x){
        if(lazy[x]){
            if(ch[x][0]){
                lazy[ ch[x][0] ] ^= 1;
                change(ch[x][0]);
            }
            if(ch[x][1]){
                lazy[ ch[x][1] ] ^= 1;
                change(ch[x][1]);
            }
            lazy[x] = 0;
        }
        if(add[x]){
            if(ch[x][0]){
                add[ ch[x][0] ] += add[x];
                val[ ch[x][0] ] += add[x];
            }
            if(ch[x][1]){
                add[ ch[x][1] ] += add[x];
                val[ ch[x][1] ] += add[x];
            }
            add[x] = 0;
        }
    }
    inline void Rotate(int x,int f){
        int y = pre[x];
        pushdown(y);
        pushdown(x);
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(pre[x]) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x;
        ch[x][f] = y;
        pre[y] = x;
        pushup(y);
    }
    inline void Splay(int x,int goal){
        pushdown(x);
        while(pre[x] != goal){
            if(pre[ pre[x] ] == goal){
                Rotate(x,ch[ pre[x] ][0] == x);
            }
            else{
                int y = pre[x],z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x){
                    Rotate(x,!f),Rotate(x,f);
                }
                else{
                    Rotate(y,f),Rotate(x,f);
                }
            }
        }
        pushup(x);
        if(goal == 0) root = x;
    }
    inline void Rotateto(int k,int goal){
        int x = root;
        while(sz[ ch[x][0] ] != k){
            if(sz[ ch[x][0] ] > k){
                x = ch[x][0];
            }
            else{
                k -= sz[ ch[x][0] ] + 1;
                x = ch[x][1];
            }
            pushdown(x);
        }
        Splay(x,goal);
    }
    inline void debug(){
        printf("root:%d\n",root);
        Travel(root);
    }
    inline void Travel(int x){
        pushdown(x);
        if(ch[x][0]) Travel(ch[x][0]);
        printf("node:%d lson:%d rson:%d pre:%d sz:%d val:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
        if(ch[x][1]) Travel(ch[x][1]);
    }
    int Newnode(int c){
        int x = ++top;
        ch[x][0] = ch[x][1] = pre[x] = 0;
        val[x] = c;
        lazy[x] = add[x] = 0;
        sz[x] = 1;
        return x;
    }
    inline void build(int &x,int l,int r,int f){
        if(l > r) return;
        int mid = (l + r) >> 1;
        x = Newnode(num[mid]);
        build(ch[x][0],l,mid - 1,x);
        build(ch[x][1],mid + 1,r,x);
        pre[x] = f;
        pushup(x);
    }
    inline void init(){
        ch[0][0] = ch[0][1] = pre[0] = 0;
        sz[0] = val[0] = 0;
        lazy[0] = add[0] = 0;
        top = root = 0;

        cnt = n;
        root = Newnode(1);
        ch[root][1] = Newnode(1);
        pre[ ch[root][1] ] = root;
        sz[root] = 2;
        for(int i = 1; i <= n;i ++) scanf("%d",&num[i]);
        build(keytree,1,n,ch[root][1]);
        pushup(ch[root][1]);
        pushup(root);
    }
    inline int findmin(int x){
        while(ch[x][0]){
            pushdown(x);
            x = ch[x][0];
        }
        return x;
    }
    inline int findmax(int x){
        while(ch[x][1]){
            pushdown(x);
            x = ch[x][1];
        }
        return x;
    }
    inline int findhead(){
        int k = 1,x = root;
        while(sz[ ch[x][0] ] != k){
            if(sz[ ch[x][0] ] > k){
                x = ch[x][0];
            }
            else{
                k -= sz[ ch[x][0] ] + 1;
                x = ch[x][1];
            }
            pushdown(x);
        }
        return x;
    }
    inline int findtail(){
        int k = cnt,x = root;
        while(sz[ ch[x][0] ] != k){
            if(sz[ ch[x][0] ] > k){
                x = ch[x][0];
            }
            else{
                k -=sz[ ch[x][0] ] + 1;
                x = ch[x][1];
            }
            pushdown(x);
        }
        return x;
    }
    inline void Add(){
        int c;
        scanf("%d",&c);
        Rotateto(0,0);
        Rotateto(k2 + 1,root);
        add[keytree] += c;
        val[keytree] += c;
    }
    inline void Rev(){
        Rotateto(0,0);
        Rotateto(k1 + 1,root);
        lazy[keytree] ^= 1;
        change(keytree);
    }
    inline void Insert(){
        int x = root,c;
        scanf("%d",&c);
        int head = findhead();
        Rotateto(1,0);
        Rotateto(2,root);
        keytree = Newnode(c);
        pre[keytree] = ch[root][1];
        pushup(ch[root][1]);
        pushup(root);
        Splay(keytree,0);
        cnt++;
    }
    inline void Del(){
        int x = findhead();
        del(x);
    }
    inline void del(int x){
        Splay(x,0);
        if(ch[x][0] == 0){
            root = ch[x][1];
            ch[x][0] = ch[x][1] = pre[x] = 0;
            pre[root] = 0;
            sz[x] = 1;
            return;
        }
        int m = findmax(ch[root][0]);
        Splay(m,root);
        ch[m][1] = ch[x][1];
        ch[x][0] = ch[x][1] = 0;
        pre[x] = 0;
        pre[ ch[m][1] ] = m;
        root = m;
        pre[root] = 0;
        pushup(root);
        sz[x] = 1;
        cnt --;
    }
    inline void Mov(){
        int tp;
        scanf("%d",&tp);
        int head,tail;
        head = findhead();
        tail = findtail();
        if(tp == 1){
            del(tail);
            Rotateto(0,0);
            Rotateto(1,root);
            ch[ ch[root][1] ][0] = tail;
            pre[tail] = ch[root][1];
            pushup(ch[root][1]);
            pushup(root);
            cnt++;
        }
        else{
            del(head);
            Rotateto(cnt ,0);
            Rotateto(cnt + 1,root);
            ch[ ch[root][1] ][0] = head;
            pre[head] = ch[root][1];
            pushup(ch[root][1]);
            pushup(root);
            cnt++;
        }
    }
    inline void Query(){
        Rotateto(1,0);
        printf("%d\n",val[root]);
    }
    int lazy[SIZEN],add[SIZEN];
    int val[SIZEN],num[SIZEN];
};
SplayTree spt;
void solve(int n,int m,int k1,int k2){
    spt.n = n;
    spt.k1 = k1;
    spt.k2 = k2;
    spt.init();
    char op[10];
    while(m--){
        scanf("%s",op);
        if(op[0] == 'a') spt.Add();
        else if(op[0] == 'r') spt.Rev();
        else if(op[0] == 'i') spt.Insert();
        else if(op[0] == 'd') spt.Del();
        else if(op[0] == 'm') spt.Mov();
        else if(op[0] == 'q') spt.Query();
    }
}
int main()
{
    //freopen("data.in","r",stdin);
    int n,m,k1,k2,txt = 1;
    while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF){
        if(!n && !m && !k1 && !k2) break;
        printf("Case #%d:\n",txt++);
        solve(n,m,k1,k2);
    }
}

这道题让我想到了开始在学习线段树的一道题,【HDU 3397】

他们的共同点就是都是由一些简单的操作组合起来,使得代码量看上去非常恐怖

这道题也是我目前写过最长的代码了,能够AC也是很开心_(:з」∠)_

题目一共给了六种操作,我是一直将队首元素放在整个二叉树的最左侧

1、add x:把从1 -- k1的数都加上x

2、reverse :把从1--k2的数进行翻转

3、insert x:把x插入到第一个元素的后面

4、delete:删除掉第一个元素

5、move 1:将队尾元素删除并插入到队首

      move 2:将队首元素删除并插入到队尾

6、询问队首元素的val

将以前做的操作全部结合起来在思路上应该是不难的,难点就在于debug

献上AC代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值