伸展树

伸展树


/*维护序列,有6种操作:
插入、删除、修改、翻转、求和、求最大子段和。*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
int IN[500010];
const int INF=1<<28;
 
struct Node
{
    Node *pre,*ch[2];
    bool rev,same;
    int sz,val,sum,MaxM,MaxL,MaxR;
}*root,buf[500010],*null;
 
Node *stack[500010];
int idx,N,M,top;
 
Node *addNode(int val)
{
    Node *p;
    if(top)p=stack[--top];
    else p=&buf[idx++];
    p->rev=p->same=false;
    p->sz=1;
    p->sum=p->val=p->MaxM=p->MaxL=p->MaxR=val;
    p->ch[0]=p->ch[1]=p->pre=null;
    return p;
}
 
inline void PushDown(Node *p)
{
    if(p==null||!p)return;
    if(p->rev)
    {
        swap(p->ch[0],p->ch[1]);
        if(p->ch[0]!=null)p->ch[0]->rev=!p->ch[0]->rev;
        if(p->ch[1]!=null)p->ch[1]->rev=!p->ch[1]->rev;
        swap(p->MaxL,p->MaxR);
        p->rev=false;
    }
    if(p->same)
    {
        p->sum=p->sz*p->val;
        p->MaxM=p->MaxL=p->MaxR=max(p->val,p->sum);
        if(p->ch[0]!=null)
        {
            p->ch[0]->val=p->val;
            p->ch[0]->same=true;
        }
        if(p->ch[1]!=null)
        {
            p->ch[1]->val=p->val;
            p->ch[1]->same=true;
        }
        p->same=false;
    }
}
 
inline void Update(Node *p)
{
    if(p==null)return;
    PushDown(p);
    PushDown(p->ch[0]);
    PushDown(p->ch[1]);
    p->sz=p->ch[0]->sz+p->ch[1]->sz+1;
    p->sum=p->val+p->ch[0]->sum+p->ch[1]->sum;
    p->MaxL=max(p->ch[0]->MaxL,p->ch[0]->sum+p->val+max(0,p->ch[1]->MaxL));
    p->MaxR=max(p->ch[1]->MaxR,p->ch[1]->sum+p->val+max(0,p->ch[0]->MaxR));
    p->MaxM=max(max(p->ch[1]->MaxL,0)+p->val+max(p->ch[0]->MaxR,0),max(p->ch[0]->MaxM,p->ch[1]->MaxM));
}
 
void Init()
{
    idx=top=0;
    null=addNode(-INF);
    null->sz=null->sum=0;
    root=addNode(-INF);
    root->sum=0;
    Node *p;
    p=addNode(-INF);
    root->ch[1]=p;
    p->pre=root;
    p->sum=0;
    Update(root->ch[1]);
    Update(root);
}
 
void Rotate(Node *x,int c)
{
    Node *y=x->pre;
    PushDown(y);PushDown(x);
    y->ch[!c]=x->ch[c];
    if(x->ch[c]!=null)
        x->ch[c]->pre=y;
    x->pre=y->pre;
    if(y->pre!=null)
        if(y->pre->ch[0]==y)
            y->pre->ch[0]=x;
        else
            y->pre->ch[1]=x;
    x->ch[c]=y;y->pre=x;
    if(y==root)root=x;
    Update(y);
}
 
void Splay(Node *x,Node *f)
{
    PushDown(x);
    while(x->pre!=f)
    {
        Node *y=x->pre,*z=y->pre;
        if(x->pre->pre==f)
            Rotate(x,x->pre->ch[0]==x);
        else
        {
            if(z->ch[0]==y)
                if(y->ch[0]==x)
                    Rotate(y,1),Rotate(x,1);
                else
                    Rotate(x,0),Rotate(x,1);
            else
                if(y->ch[1]==x)
                    Rotate(y,0),Rotate(x,0);
                else
                    Rotate(x,1),Rotate(x,0);
        }
    }
    Update(x);
}
 
Node* Select(int kth)
{
    int tmp;
    Node *t=root;
    while(1)
    {
        PushDown(t);
        tmp=t->ch[0]->sz;
        if(tmp+1==kth)break;
        if(kth<=tmp)
            t=t->ch[0];
        else
        {
            kth-=tmp+1;
            t=t->ch[1];
        }
    }
    return t;
}
 
Node * Build(int l,int r)
{
    if(l>r)return null;
    int mid=(l+r)>>1;
    Node *p=addNode(IN[mid]);
    p->ch[0]=Build(l,mid-1);
    if(p->ch[0]!=null)
        p->ch[0]->pre=p;
    p->ch[1]=Build(mid+1,r);
    if(p->ch[1]!=null)
        p->ch[1]->pre=p;
    Update(p);
    return p;
}
 
void Recycle(Node *p)
{
    if(p->ch[0]!=null)Recycle(p->ch[0]);
    if(p->ch[1]!=null)Recycle(p->ch[1]);
    stack[top++]=p;
}
 
void Delete(int pos,int tot)
{
    Splay(Select(pos-1),null);
    Splay(Select(pos+tot),root);
    if(root->ch[1]->ch[0]!=null)
    {
        Recycle(root->ch[1]->ch[0]);
        root->ch[1]->ch[0]=null;
    }
    Update(root->ch[1]);Update(root);
    Splay(root->ch[1],null);
}
 
void Insert(int pos,int tot)
{
    for(int i=1;i<=tot;i++)
        scanf("%d",IN+i);
    Node *troot=Build(1,tot);
    Splay(Select(pos),null);
    Splay(Select(pos+1),root);
    root->ch[1]->ch[0]=troot;
    troot->pre=root->ch[1];
    Update(root->ch[1]);Update(root);
    Splay(troot,null);
}
 
void Reverse(int pos,int tot)
{
    Splay(Select(pos-1),null);
    Splay(Select(pos+tot),root);
    if(root->ch[1]->ch[0]!=null)
    {
        root->ch[1]->ch[0]->rev=!root->ch[1]->ch[0]->rev;
        Splay(root->ch[1]->ch[0],null);
    }
}
 
void GetSum(int pos,int tot)
{
    Splay(Select(pos-1),null);
    Splay(Select(pos+tot),root);
    printf("%d\n",root->ch[1]->ch[0]->sum);
}
 
void MakeSame(int pos,int tot)
{
    int c;
    scanf("%d",&c);
    Splay(Select(pos-1),null);
    Splay(Select(pos+tot),root);
    root->ch[1]->ch[0]->val=c;
    root->ch[1]->ch[0]->same=true;
    Splay(root->ch[1]->ch[0],null);
}
 
void MaxSum()
{
    Splay(Select(1),null);
    Splay(Select(root->sz),root);
    printf("%d\n",root->ch[1]->ch[0]->MaxM);
}
 
void T(Node *p)
{
    if(p->ch[0]!=null)T(p->ch[0]);
    printf("%d ",p->val);
    if(p->ch[1]!=null)T(p->ch[1]);
}
 
int main()
{
    scanf("%d%d",&N,&M);
    Init();
    for(int i=1;i<=N;i++)
        scanf("%d",IN+i);
    Node *troot=Build(1,N);
    root->ch[1]->ch[0]=troot;
    troot->pre=root->ch[1];
    Update(root->ch[1]);
    Update(root);
    while(M--)
    {
        char com[20];
        scanf("%s",com);
        int a,b;
        if(com[2]!='X')
            scanf("%d%d",&a,&b);
        switch(com[2])
        {
            case 'S':Insert(a+1,b);break;
            case 'L':Delete(a+1,b);break;
            case 'V':Reverse(a+1,b);break;
            case 'K':MakeSame(a+1,b);break;
            case 'T':GetSum(a+1,b);break;
            case 'X':MaxSum();break;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值