BZOJ 2329 括号修复(splay)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2329

题意:

BZOJ 2329 括号修复(splay)_第1张图片

思路:此题除了Replace操作外与BZOJ2209一样。那么多了一个Replace操作,要注意,这个操作与Invert操作有先后之分。若Replace早于Invert发生,那么在Invert操作发生时要将Replace的标记取反,这样pushDown时先Invert再Replace;若Replace晚于Invert,则Invert操作可以忽略。


struct node
{
    int op1,op2,op3,val,LMin,LMax,RMin,RMax,sum;
    int size;
    node *c[2],*p;
    
    void invert()
    {
        val*=-1; sum*=-1;
        int temp;
        temp=LMin; LMin=-LMax; LMax=-temp;
        temp=RMin; RMin=-RMax; RMax=-temp;
        op1^=1;
        if(op3) op3*=-1;
    }




    void turnover()
    {
        swap(LMin,RMin);
        swap(LMax,RMax);
        swap(c[0],c[1]);
        op2^=1;
    }
    
    
    void replace(int x)
    {
        op1=0;
        op3=x;
        val=x;
        if(x==1)
        {
            sum=size;
            LMin=0; LMax=size;
            RMin=0; RMax=size;
        }
        else
        {
            sum=-size;
            LMin=-size; LMax=0;
            RMin=-size; RMax=0;
        }
    }
};




node a[N],*root,*nullNode;
int cnt;




void pushUp(node *p)
{
    if(p==nullNode) return;
    
    p->size=1+p->c[0]->size+p->c[1]->size;
    p->sum=p->c[0]->sum+p->val+p->c[1]->sum;




    p->LMin=p->c[0]->LMin;
    p->LMin=min(p->LMin,p->c[0]->sum+p->val);
    p->LMin=min(p->LMin,p->c[0]->sum+p->val+p->c[1]->LMin);




    p->LMax=p->c[0]->LMax;
    p->LMax=max(p->LMax,p->c[0]->sum+p->val);
    p->LMax=max(p->LMax,p->c[0]->sum+p->val+p->c[1]->LMax);




    p->RMin=p->c[1]->RMin;
    p->RMin=min(p->RMin,p->c[1]->sum+p->val);
    p->RMin=min(p->RMin,p->c[1]->sum+p->val+p->c[0]->RMin);




    p->RMax=p->c[1]->RMax;
    p->RMax=max(p->RMax,p->c[1]->sum+p->val);
    p->RMax=max(p->RMax,p->c[1]->sum+p->val+p->c[0]->RMax);
}




int ok(node *p)
{
    return p!=nullNode&&(p!=&a[1])&&(p!=&a[2]);
}




void pushDown(node *p)
{
    if(p==nullNode) return;
    if(p->op1)
    {
        if(ok(p->c[0])) p->c[0]->invert();
        if(ok(p->c[1])) p->c[1]->invert();
        p->op1=0;
    }
    if(p->op2)
    {
        if(ok(p->c[0])) p->c[0]->turnover();
        if(ok(p->c[1])) p->c[1]->turnover();
        p->op2=0;
    }
    
    if(p->op3)
    {
        if(ok(p->c[0])) p->c[0]->replace(p->op3);
        if(ok(p->c[1])) p->c[1]->replace(p->op3);
        p->op3=0;
    }
}




node *newNode(int val,node *p)
{
    node *e=&a[cnt++];
    e->c[0]=e->c[1]=nullNode;
    e->p=p;
    e->op1=e->op2=e->op3=0;
    e->size=1;
    e->sum=e->val=e->LMin=e->RMin=e->LMax=e->RMax=val;
    return e;
}




void init()
{
    nullNode=0;
    nullNode=newNode(0,nullNode);
    nullNode->size=0;
    nullNode->LMin=nullNode->RMin=INF;
    nullNode->LMax=nullNode->RMax=-INF;
    nullNode->sum=0;




    root=newNode(0,nullNode);
    root->LMin=root->RMin=INF;
    root->LMax=root->RMax=-INF;
    root->sum=0;
    root->c[1]=newNode(0,root);
    root->c[1]->LMin=root->c[1]->RMin=INF;
    root->c[1]->LMax=root->c[1]->RMax=-INF;
    root->c[1]->sum=0;
    pushUp(root);
}








void zig(node *x)
{
    node *p=x->p,*q=p->p;
    p->c[0]=x->c[1];
    if(x->c[1]!=nullNode) x->c[1]->p=p;
    x->c[1]=p;
    p->p=x;
    x->p=q;
    if(q!=nullNode)
    {
        if(q->c[0]==p) q->c[0]=x;
        else q->c[1]=x;
    }
    pushUp(p);
    pushUp(x);
    if(root==p) root=x;
}




void zag(node *x)
{
    node *p=x->p,*q=p->p;
    p->c[1]=x->c[0];
    if(x->c[0]!=nullNode) x->c[0]->p=p;
    x->c[0]=p;
    p->p=x;
    x->p=q;
    if(q!=nullNode)
    {
        if(q->c[0]==p) q->c[0]=x;
        else q->c[1]=x;
    }
    pushUp(p);
    pushUp(x);
    if(root==p) root=x;
}




void splay(node *x,node *goal)
{
    while(x->p!=goal)
    {
        if(x->p->p!=goal)
        {
            pushDown(x->p->p);
            pushDown(x->p);
            pushDown(x);
            if(x->p->p->c[0]==x->p)
            {
                if(x->p->c[0]==x) zig(x->p),zig(x);
                else zag(x),zig(x);
            }
            else
            {
                if(x->p->c[1]==x) zag(x->p),zag(x);
                else zig(x),zag(x);
            }
        }
        else
        {
            pushDown(x->p);
            pushDown(x);
            if(x->p->c[0]==x) zig(x);
            else zag(x);
        }
    }
}




void select(int k,node *goal)
{
    node *p=root;
    pushDown(p);
    while(k!=p->c[0]->size+1)
    {
        if(k<=p->c[0]->size) p=p->c[0];
        else
        {
            k-=1+p->c[0]->size;
            p=p->c[1];
        }
        pushDown(p);
    }
    splay(p,goal);
}




node *build(int L,int R,char str[],node *p)
{
    if(L>R) return nullNode;
    int mid=(L+R)>>1;
    node *e=newNode(str[mid]=='('?1:-1,p);
    e->c[0]=build(L,mid-1,str,e);
    e->c[1]=build(mid+1,R,str,e);
    pushUp(e);
    return e;
}




void insert(int p,int n,char str[])
{
    select(p+1,nullNode);
    select(p+2,root);
    node *e=build(1,n,str,root->c[1]);
    root->c[1]->c[0]=e;
    splay(e,nullNode);
}




int query(int L,int R)
{
    select(L,nullNode);
    select(R+2,root);
    node *p=root->c[1]->c[0];
    return -(p->LMin-1)/2+(p->RMax+1)/2;
}




void invert(int L,int R)
{
    select(L,nullNode);
    select(R+2,root);
    node *p=root->c[1]->c[0];
    p->invert();
    splay(p,nullNode);
}


void rep(int L,int R,int x)
{
    select(L,nullNode);
    select(R+2,root);
    node *p=root->c[1]->c[0];
    p->replace(x);
    splay(p,nullNode);
}


void turnover(int L,int R)
{
    select(L,nullNode);
    select(R+2,root);
    node *p=root->c[1]->c[0];
    p->turnover();
    splay(p,nullNode);
}




int n,m;
char str[N];


int main()
{
    init(); RD(n,m); RD(str+1); insert(0,n,str);
    int x,y;
    char op[10],S[10];
    while(m--)
    {
        RD(op);RD(x,y);
        if(strcmp(op,"Query")==0)  PR(query(x,y));
        else if(strcmp(op,"Invert")==0) invert(x,y);
        else if(strcmp(op,"Swap")==0)  turnover(x,y);
        else if(strcmp(op,"Replace")==0) RD(S),rep(x,y,S[0]=='('?1:-1);
    }
}

你可能感兴趣的:(play)