hdu 4453 Looploop(splay)

hdu4454Looploop


一看到有旋转操作就splay了

做两个lazy标记: flip(旋转), add(增加)


六种操作

增加,删除,旋转,插入,移动,查询

1.add增加:add(x) 对前k2个数字增加x

将从箭头指向位置开始前k2个节点从树中分离,分离出来的根节点add+x,再将两棵树合并 


2.reverse旋转:  将前k1个数字颠倒过来

从箭头指向位置开始前k1个节点从书中分离,分离出来的根节点flip=1, 再将两棵树合并


3.insert插入: insert(x) 在箭头指向位置的后面插入一个x

将指向位置伸展为树根,那么其他所有的节点都在根的右孩子,在根与根的右孩子前插入x即可,节点数n+1


4.delete删除:将箭头指向位置的数字删除,箭头顺时针移动一个位置(右移/后移)

将指向位置伸展为树根,那么其他所有的节点都在根的右孩子,将树根删除,将原树根右孩子设为新根,节点数n-1


5.move移动:move(x), x=1箭头逆时针移动(左移/前移),x=2箭头顺时针移动(右移/后移)

x=1 将n位置的节点从树中分离,将原根设为其右孩子:root=splay(n),root->child[1]=splay(1);

x=2与此类似


6.query查询:输出箭头指向位置的数字

将指向位置伸展为树根,root=splay(1),output:root->value



 ===========================================================


刚开始new节点,果断超时,后来开了数组,newnode(int) 替换new node(int)

node lk[maxn];
int cnt;
node* newnode(int v)
{
    lk[cnt]=node(v);
    return lk+cnt++;
}

build(root, 1, N);
cnt=0;
一直是运行出错调试了一上午 = = 。。。。。。。飙泪


最后发现cnt出了问题,竟然sb的build之后cnt=0.。。


代码如下: 343ms

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 2e5+5;
int N, M, K1, K2;

int hdu[maxn];
struct node
{
    node *child[2];
    int size;
    int value;
    int flip;
    int add;
    node ();
    node(int);
    void pushup();
    void pushdown();
    int rank();
    int cmp(int k);
}null, *root, lk[maxn];
int cnt;
node* newnode(int v)
{lk[cnt]=node(v);
    return lk+cnt++;
}
int node:: cmp(int k)
{
    if(k==rank()) return -1;
    return k < rank() ? 0 : 1;
}
int node:: rank()
{
    return child[0]->size+1;
}
void node:: pushdown()
{
    if(flip)
    {
        swap(child[0], child[1]);
        child[0]->flip^=1;
        child[1]->flip^=1;
        flip=0;
    }
    if(add)
    {
        value+=add;
        child[0]->add+=add;
        child[1]->add+=add;
        add=0;
    }
}
void node:: pushup()
{
    size=child[0]->size+child[1]->size+1;
}
node:: node()
{
    child[0]=child[1]=&null;
    size=0;
    flip=0;
    add=0;
}
node:: node(int _value): value(_value)
{
    child[0]=child[1]=&null;
    size=1;
    flip=0;
    add=0;
}
void rotate(node*&o, int d)
{
    o->pushdown();
    node *t=o->child[d];
    t->pushdown();
    o->child[d]=t->child[d^1];
    t->child[d^1]=o;
    o->pushup();
    o=t;
    o->pushup();
}
void splay(node*& o, int k)
{
    o->pushdown();
    int d=o->cmp(k);
    if(~d)
    {
        if(d) splay(o->child[d], k-o->rank());
        else splay(o->child[d], k);
        rotate(o, d);
    }
}
void build(node*&o, int l ,int r)
{
    int m= (l+r)>>1;
    o=newnode(hdu[m]);

    if(m>l) build(o->child[0], l, m-1);
    if(m<r) build(o->child[1], m+1, r);

    o->pushup();
}

void add(int x)
{
    splay(root, K2);
    root->value+=x;
    root->child[0]->add+=x;
}
void reverse()
{
    splay(root, K1);

    node*temp=root->child[1];
    root->child[1]=&null;
    root->pushup();

    root->flip=1;
    root->pushdown();
    splay(root, K1);

    root->child[1]=temp;
    root->pushup();
}
void insert(int x)
{
    splay(root, 1);

    node *temp=newnode(x);
    temp->child[1]=root->child[1];
    temp->pushup();

    root->child[1]=temp;
    root->pushup();

    N++;
}
void remove()
{
    splay(root, 1);
    node *temp=root->child[1];
    root=temp;
    root->pushdown();

    N--;
}
void move(int x)
{
    if(x==1)
    {
        splay(root, N);
        node *temp = root->child[0];
        root->child[0]=&null;

        temp->pushdown();
        splay(temp, 1);
        root->child[1]=temp;
        root->pushup();
    }
    else
    {
        splay(root, 1);
        node *temp = root->child[1];
        root->child[1]=&null;

        temp->pushdown();
        splay(temp, N-1);
        root->child[0]=temp;
        root->pushup();
    }
}

int main()
{
    int kase=1;
    while(cin>>N>>M>>K1>>K2 && N|M|K1|K2)
    {
        for(int i=1;i<=N;i++) scanf("%d", hdu+i); cnt=0;
        build(root, 1, N);
        printf("Case #%d:\n", kase++);
        while(M--)
        {
            char op1[10]; scanf("%s", op1);
            if(!strcmp(op1, "add"))
            {
                int op2; scanf("%d", &op2);
                add(op2);
            }
            else if(!strcmp(op1, "reverse"))
            {
                reverse();
            }
            else if(!strcmp(op1, "insert"))
            {
                int op2; scanf("%d", &op2);
                insert(op2);
            }
            else if(!strcmp(op1, "delete"))
            {
                remove();
            }
            else if(!strcmp(op1, "move"))
            {
                int op2; scanf("%d", &op2);
                move(op2);
            }
            else
            {
                splay(root, 1);
                printf("%d\n", root->value);
            }
        }
    }
    return 0;
}





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值