爱悠闲 > BZOJ 1493 NOI2007 项链工厂

BZOJ 1493 NOI2007 项链工厂

分类: BZOJ  |  标签: BZOJ,BZOJ1493,NOI2007,Splay  |  作者: popoqqq 相关  |  发布日期 : 2014-09-24  |  热度 : 547°

题目大意:维护一个环,每个点有一个颜色,提供6种操作:

1.将这个环顺时针旋转k

2.沿点1所在直径翻转

3.将两个珠子互换

4.将一段区间染色

5.查询这个环上有多少颜色段

6.查询一段区间有多少颜色段

关于颜色段通用的处理方法是每个区间记录三个值,颜色段数、左端点颜色、右端点颜色,合并时颜色段数相加,如果左区间右端点和右区间左端点颜色相同则减一

然后用Splay维护区间即可 不过这题还是有一些小细节需要处理

首先null节点要保证不会被修改 然后更新的时候特判 如果一段区间颜色是0直接返回另一区间即可

翻转时要把2~n翻转 不能翻转1~n

互换时直接交换必死 因为两个节点上面可能会有标记 正确的做法是把两个节点都旋转上来,这样保证没有标记 然后交换颜色并维护即可

询问环上的颜色段时直接cnt-(lcolor==rcolor)就挂了 因为当整个环都是同种颜色的时候前面那个表达式等于0 所以要特判等于0的时候输出1

写这题时候各种脑残,旋转不换根,Find函数传参传的0,写完都做好测数据的准备了,结果交上1A。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct color_segment{
    int cnt,lcolor,rcolor;
    color_segment(int x)
    {
        cnt=1;
        if(!x)
            cnt=0;
        lcolor=rcolor=x;
    }
};
color_segment operator + (const color_segment x,const color_segment y)
{
    color_segment re(0);
    re.lcolor=x.lcolor?x.lcolor:y.lcolor;
    re.rcolor=y.rcolor?y.rcolor:x.rcolor;
    re.cnt=x.cnt+y.cnt-(x.rcolor==y.lcolor);
    return re;
}
struct abcd{
    int num,siz;
    abcd *fa,*ls,*rs;
    color_segment *s;
    int rev_mark,change_mark;
    abcd(int x);
    void Push_Up();
    void Push_Down();
}*null=new abcd(0),*root=null;
abcd :: abcd(int x)
{
    num=x;
    siz=1;
    if(!x)
        siz=0;
    fa=ls=rs=null;
    rev_mark=change_mark=0;
    s=new color_segment(x);
}
void abcd :: Push_Up()
{
    siz=ls->siz+rs->siz+1;
    *s=(*ls->s)+color_segment(num)+(*rs->s);
}
void abcd :: Push_Down()
{
    if(rev_mark)
    {
        ls->rev_mark^=1;
        rs->rev_mark^=1;
        swap(ls->ls,ls->rs);
        swap(rs->ls,rs->rs);
        swap(ls->s->lcolor,ls->s->rcolor);
        swap(rs->s->lcolor,rs->s->rcolor);
        rev_mark=0;
    }
    if(change_mark)
    {
        if(ls!=null)
        {
            ls->num=ls->change_mark=change_mark;
            *ls->s=color_segment(change_mark);
        }
        if(rs!=null)
        {
            rs->num=rs->change_mark=change_mark;
            *rs->s=color_segment(change_mark);
        }
        change_mark=0;
    }
}
void Zig(abcd *x)
{
    abcd *y=x->fa;
    y->Push_Down();
    x->Push_Down();
    y->ls=x->rs;
    x->rs->fa=y;
    x->rs=y;
    x->fa=y->fa;
    if(y==y->fa->ls)
        y->fa->ls=x;
    else if(y==y->fa->rs)
        y->fa->rs=x;
    y->fa=x;
    y->Push_Up();
    if(y==root)
        root=x;
}
void Zag(abcd *x)
{
    abcd *y=x->fa;
    y->Push_Down();
    x->Push_Down();
    y->rs=x->ls;
    x->ls->fa=y;
    x->ls=y;
    x->fa=y->fa;
    if(y==y->fa->ls)
        y->fa->ls=x;
    else if(y==y->fa->rs)
        y->fa->rs=x;
    y->fa=x;
    y->Push_Up();
    if(y==root)
        root=x;
}
void Splay(abcd *x,abcd *Tar)
{
    while(1)
    {
        abcd *y=x->fa,*z=y->fa;
        if(y==Tar)
            break;
        if(z==Tar)
        {
            if(x==y->ls) Zig(x);
            else Zag(x);
            break;
        }
        if(x==y->ls)
        {
            if(y==z->ls)
                Zig(y);
            Zig(x);
        }
        else
        {
            if(y==z->rs)
                Zag(y);
            Zag(x);
        }
    }
    x->Push_Up();
}
void Find(abcd *x,int y,abcd *z)
{
    while(1)
    {
        x->Push_Down();
        if(y<=x->ls->siz)
            x=x->ls;
        else
        {
            y-=x->ls->siz;
            if(y==1)
                break;
            y--;
            x=x->rs;
        }
    }
    Splay(x,z);
}
void Insert(abcd *&x,int y,abcd *z)
{
    if(x==null)
    {
        x=new abcd(y);
        x->fa=z;
        Splay(x,null);
        return ;
    }
    x->Push_Down();
    Insert(x->rs,y,x);
}
int n,m,c;
int main()
{
    int i,x,y,z;
    char p[10];
    cin>>n>>c;
    Insert(root,19980402,null);
    for(i=1;i<=n;i++)
        scanf("%d",&x),Insert(root,x,null);
    Insert(root,19980402,null);
    cin>>m;
    for(i=1;i<=m;i++)
    {
        scanf("%s",p);
        if(p[0]=='R')
        {
            scanf("%d",&x);
            Find(root,n-x+1,null);
            Find(root,n+2,root);
            abcd *temp=root->rs->ls;
            root->rs->ls=null;
            root->rs->Push_Up();
            root->Push_Up();
            Find(root,1,null);
            Find(root,2,root);
            root->rs->ls=temp;
            temp->fa=root->rs;
            root->rs->Push_Up();
            root->Push_Up();
        }
        else if(p[0]=='F')
        {
            Find(root,2,null);
            Find(root,n+2,root);
            abcd *temp=root->rs->ls;
            temp->rev_mark^=1;
            swap(temp->ls,temp->rs);
            swap(temp->s->lcolor,temp->s->rcolor);
        }
        else if(p[0]=='S')
        {
            scanf("%d%d",&x,&y);
            if(x==y)
                continue;
            if(x>y)
                swap(x,y);
            Find(root,x+1,null);
            Find(root,y+1,root);
            swap(root->rs->num,root->num);
            root->rs->Push_Up();
            root->Push_Up();
        }
        else if(p[0]=='P')
        {
            scanf("%d%d%d",&x,&y,&z);
            if(x<=y)
            {
                Find(root,x,null);
                Find(root,y+2,root);
                abcd *temp=root->rs->ls;
                temp->num=temp->change_mark=z;
                *temp->s=color_segment(z);
            }
            else
            {
                Find(root,x,null);
                Find(root,n+2,root);
                abcd *temp=root->rs->ls;
                temp->num=temp->change_mark=z;
                *temp->s=color_segment(z);
                Find(root,1,null);
                Find(root,y+2,root);
                temp=root->rs->ls;
                temp->num=temp->change_mark=z;
                *temp->s=color_segment(z);
            }
        }
        else if(p[0]=='C'&&p[1]==0)
        {
            Find(root,1,null);
            Find(root,n+2,root);
            abcd *temp=root->rs->ls;
            z=temp->s->cnt-(temp->s->lcolor==temp->s->rcolor);
            if(!z)++z;
            printf("%d\n",z);
        }
        else{
            scanf("%d%d",&x,&y);
            if(x<=y)
            {
                Find(root,x,null);
                Find(root,y+2,root);
                abcd *temp=root->rs->ls;
                printf("%d\n",temp->s->cnt);
            }
            else
            {
                Find(root,x,null);
                Find(root,n+2,root);
                abcd *temp=root->rs->ls;
                color_segment s=*temp->s;
                Find(root,1,null);
                Find(root,y+2,root);
                temp=root->rs->ls;
                s=s+*temp->s;
                printf("%d\n", s.cnt );
            }
        }
    }
}