BZOJ 1493 项链工厂(splay)

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

题意:

BZOJ 1493 项链工厂(splay)_第1张图片

BZOJ 1493 项链工厂(splay)_第2张图片

BZOJ 1493 项链工厂(splay)_第3张图片

思路:(1)R:其实就是将[n-k+1,n]与[1,n-k]两段互换位置;

(2)F:其实就是将[2,n]翻转;

(3)S:首先得到L、R位置的颜色x,y,然后利用(4),将[L,L]置为y,将[R,R]置为x;

(4)P:当L<=R时就是一般的,即将L-1和R+1转到根节点以及根节点的右子树,则[L,R]落在根节点右子树的左子树,直接修改标记即可;若L>R,则先利用(1),转n-L+1个,然后要染色的就是[1,R+n-L+1],最后再转L-1复原;

(5)C:得到1位置和n位置的颜色,若相同则答案减去1;

(6)CS:这个直接统计[L,R]即可;与(4)类似,也有L>R的时候。

 
 
struct node
{
    int L,R,C,segCnt,flag,size,rev;
    node *c[2],*f;
    
    void set(int color)
    {
        L=R=C=color;
        segCnt=1;
        flag=color;
    }
    
    void reverse()
    {
        rev^=1;
        swap(L,R);
        swap(c[0],c[1]);
    }
};


int n,m;


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


void pushUp(node *x)
{
    if(x==nullNode) return;
    
    x->segCnt=x->c[0]->segCnt+1+x->c[1]->segCnt;
    if(x->c[0]!=nullNode&&x->c[0]->R==x->C) x->segCnt--;
    if(x->c[1]!=nullNode&&x->c[1]->L==x->C) x->segCnt--;
    
    x->L=x->R=x->C;
    if(x->c[0]!=nullNode) x->L=x->c[0]->L;
    if(x->c[1]!=nullNode) x->R=x->c[1]->R;
    
    x->size=x->c[0]->size+1+x->c[1]->size;
}


void pushDown(node *x)
{
    if(x==nullNode) return;
    if(x->flag)
    {
        if(x->c[0]!=nullNode)x->c[0]->set(x->flag);
        if(x->c[1]!=nullNode)x->c[1]->set(x->flag);
        x->flag=0;
    } 
    if(x->rev)
    {
        if(x->c[0]!=nullNode)x->c[0]->reverse();
        if(x->c[1]!=nullNode)x->c[1]->reverse();
        x->rev=0;
    }
}


void zig(node *x)
{
    node *p=x->f,*q=p->f;
    p->c[0]=x->c[1];
    if(x->c[1]!=nullNode) x->c[1]->f=p;
    x->c[1]=p;
    p->f=x;
    x->f=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->f,*q=p->f;
    p->c[1]=x->c[0];
    if(x->c[0]!=nullNode) x->c[0]->f=p;
    x->c[0]=p;
    p->f=x;
    x->f=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->f!=goal)
    {
        if(x->f->f!=goal)
        {
            pushDown(x->f->f);
            pushDown(x->f);
            pushDown(x);
            if(x->f->f->c[0]==x->f)
            {
                if(x->f->c[0]==x) zig(x->f),zig(x);
                else zag(x),zig(x);
            }
            else 
            {
                if(x->f->c[1]==x) zag(x->f),zag(x);
                else zig(x),zag(x);
            }
        }
        else
        {
            pushDown(x->f);
            pushDown(x);
            if(x->f->c[0]==x) zig(x);
            else zag(x);
        }
    }
}


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




void print()
{
    int i;
    FOR1(i,n)
    {
        select(i+1,nullNode);
        printf("%d ",root->C);
    }
    puts("");
}




node *newNode(int c,node *p)
{
    node *x=&a[e++];
    x->L=x->R=x->C=c;
    x->segCnt=1;
    x->size=1;
    x->flag=0;
    x->rev=0;
    x->f=p;
    x->c[0]=x->c[1]=nullNode;
    return x;
}


void init()
{
    nullNode=0;
    nullNode=newNode(0,nullNode);
    nullNode->size=0;
    nullNode->segCnt=0;
    
    root=newNode(0,nullNode);
    root->c[1]=newNode(0,root);
    pushUp(root);
}


node *build(int L,int R,int b[],node *p)
{
    if(L>R) return nullNode;
    int mid=(L+R)>>1;
    node *x=newNode(b[mid],p);
    if(L==R) return x;
    x->c[0]=build(L,mid-1,b,x);
    x->c[1]=build(mid+1,R,b,x);
    pushUp(x);
    return x;
}


void insert(int pos,int n,int b[])
{
    select(pos+1,nullNode);
    select(pos+2,root);
    node *x=root->c[1];
    node *y=build(1,n,b,x);
    x->c[0]=y;
    splay(x,nullNode);
}




void rotate(int k)
{
    if(k==0||k==n) return;
    select(n-k+1,nullNode);
    select(n+2,root);
    node *x=root->c[1];
    node *y=x->c[0];
    
    x->c[0]=nullNode;
    splay(x,nullNode);
    y->f=nullNode;
    
    select(1,nullNode);
    select(2,root);
    x=root->c[1];
    x->c[0]=y;
    y->f=x;
    splay(x,nullNode);
}


void flip()
{
    if(n<=2) return;
    select(2,nullNode);
    select(n+2,root);
    
    node *x=root->c[1]->c[0];
    x->reverse();
    splay(x,nullNode);
}


int getColor(int pos)
{
    select(pos+1,nullNode);
    return root->C;
}




void paint(int L,int R,int c)
{
    if(L<=R)
    {
        select(L,nullNode);
        select(R+2,root);
        node *x=root->c[1]->c[0];
        x->set(c);
        splay(x,nullNode);
    }
    else
    {
        rotate(n-L+1);
        paint(1,R+n-L+1,c);
        rotate(L-1);
    }
}


void Swap(int L,int R)
{
    if(L==R) return;
    int x=getColor(L);
    int y=getColor(R);
    paint(L,L,y);
    paint(R,R,x);
}




int Count()
{
    if(n==0) return 0;
    int x=getColor(1);
    int y=getColor(n);
    int ans=root->segCnt-2;
    if(x==y) return max(ans-1,1);
    return ans;
}




void print(node *x)
{
    if(x==nullNode) return;
    print(x->c[0]);
    printf("%d ",x->C);
    print(x->c[1]);
}


int countSegment(int L,int R)
{
    if(L<=R)
    {
        select(L,nullNode);
        select(R+2,root);
        return root->c[1]->c[0]->segCnt;
    }
    else
    {
        rotate(n-L+1);
        int ans=countSegment(1,R+n-L+1);
        rotate(L-1);
        return ans;
    }
}


int b[N];




int main()
{
    init();
    RD(n,m);
    int i;
    FOR1(i,n) RD(b[i]);
    insert(0,n,b);
    RD(m);
    int x,y,z;
    char op[5];


    
    while(m--)
    {
        RD(op);
        if(op[0]=='R') RD(x),rotate(x);
        else if(op[0]=='F') flip();
        else if(op[0]=='S') RD(x,y),Swap(x,y);
        else if(op[0]=='P') RD(x,y,z),paint(x,y,z);
        else if(op[0]=='C'&&op[1]==0) PR(Count());
        else RD(x,y),PR(countSegment(x,y));
    }
}


你可能感兴趣的:(play)