BZOJ1500 维护数列 treap实现

很早以前听叉姐说treap可以写这个题,然后围观了一下神代码,然后~发现这个比用splay写起来简单很多。

这里首先要改变一下treap的写法。正常的treap是每个节点维护一个权值,然后根据权值去旋转,这样我们可以把一棵treap分成两棵,方法是造一个没用的节点然后给这个结点一个极大权值,这样这个节点就是根结点,它的左右两棵子村就是把原来的树分成了两棵,这样我们就能很轻松的提取出一个区间并像splay一样维护。

然后~其实吧~我用的不是旋转的方法提取区间,而是用split和merge把一棵树拆成两棵和把两棵合并成一棵。具体的实现可以看我下面的代码。

一开始这个题老是TLE,后来发现竟然是因为我用了系统的rand函数导致的,然后~自己写了一个随机数生成器~然后过掉~但是还是比splay慢【囧

SPOJ1470我还没去尝试~不过我觉得目测应该会TLE掉~毕竟SPOJ连优化不好的splay都会TLE掉。唉

#define INF 2000000000
#define N 500010
struct Node;
Node *null,*root;
struct Node
{
    int w,sz,val,sum,ls,rs,ss,lzy1,lzy2;
    Node *lft,*rht;
    void split(int,Node*&,Node*&);
    void same(int v)
    {
        if(this==null) return;
        lzy2=val=v;
        sum=v*sz;
        ls=rs=ss=max(sum,v);
    }
    void rev()
    {
        if(this==null) return;
        lzy1^=1;
        swap(lft,rht);
        swap(ls,rs);
    }
    Node *pushup()
    {
        sz=lft->sz+1+rht->sz;
        sum=lft->sum+val+rht->sum;
   
        ls=max(lft->ls,lft->sum+val+max(0,rht->ls));
        rs=max(rht->rs,rht->sum+val+max(0,lft->rs));
   
        ss=max(0,lft->rs)+val+max(0,rht->ls);
        ss=max(ss,max(lft->ss,rht->ss));
   
        return this;
    }
    Node *pushdown()
    {
        if(lzy1)
        {
            lft->rev();
            rht->rev();
            lzy1=0;
        }
        if(lzy2!=-INF)
        {
            lft->same(lzy2);
            rht->same(lzy2);
            lzy2=-INF;
        }
        return this;
    }
};
Node *merge(Node *p,Node *q)
{
    if(p==null) return q;
    if(q==null) return p;
    if(p->w<q->w)
    {
        p->pushdown();
        p->rht=merge(p->rht,q);
        return p->pushup();
    }
    q->pushdown();
    q->lft=merge(p,q->lft);
    return q->pushup();
}
void Node::split(int need,Node *&p,Node *&q)
{
    if(this==null)
    {
        p=q=null;
        return;
    }
    pushdown();
    if(lft->sz>=need)
    {
        lft->split(need,p,q);
        lft=null;
        pushup();
        q=merge(q,this);
        return;
    }
    rht->split(need-(lft->sz+1),p,q);
    rht=null;
    pushup();
    p=merge(this,p);
    return;
}
Node data[N],*pool[N];
int top,cnt;
Node* newnode(int c)
{
    Node *x;
    if(top) x=pool[top--];
    else x=&data[cnt++];
    x->lft=x->rht=null;
    x->sz=1; x->lzy1=0; x->lzy2=-INF;
    x->val=x->sum=x->ls=x->rs=x->ss=c;
    x->w=rands();
    return x;
}
void init()
{
    cnt=1; top=0;
    null=&data[0];
    null->sz=null->sum=0;
    null->val=null->ls=null->rs=null->ss=-INF;
    null->lzy1=0;
    null->lzy2=-INF;
    null->lft=null->rht=null;
}
//---------------------------------------------------------
void erase(Node *rt)
{
    if(rt==null) return;
    erase(rt->lft);
    erase(rt->rht);
    pool[++top]=rt;
}
int n,m;
char ord[20];
int a,b,c;
int main ()
{
init();
        root=null;
        n=fastget();
        m=fastget();
        for(int i=0;i<n;i++)
        {
            a=fastget();
            root=merge(root,newnode(a));
        }
        while (m--)
        {
            scanf("%s",ord);
            Node *p,*q,*r,*s;
            if(ord[0]=='I')
            {
                a=fastget();
                n=fastget();
                root->split(a,p,q);
                for(int i=0;i<n;i++)
                {
                    b=fastget();
                    p=merge(p,newnode(b));
                }
                root=merge(p,q);
            }else if(ord[0]=='D')
            {
                a=fastget();
                b=fastget();
                b=a+b-1;
                root->split(a-1,p,q);
                q->split(b-a+1,r,s);
                erase(r);
                root=merge(p,s);
            }else if(ord[0]=='M' && ord[2]=='K')
            {
                a=fastget();
                b=fastget();
                c=fastget();
                b=b+a-1;
                root->split(a-1,p,q);
                q->split(b-a+1,r,s);
                r->same(c);
                root=merge(p,merge(r,s));
            }else if(ord[0]=='R')
            {
                a=fastget();
                b=fastget();
                b=b+a-1;
                root->split(a-1,p,q);
                q->split(b-a+1,r,s);
                r->rev();
                root=merge(p,merge(r,s));
            }else if(ord[0]=='G')
            {
                a=fastget();
                b=fastget();
                b=a+b-1;
                root->split(a-1,p,q);
                q->split(b-a+1,r,s);
                fastput(r->sum);
                root=merge(p,merge(r,s));
            }
            else if(ord[0]=='M') fastput(root->ss);
        }
      
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值