BZOJ1494:[NOI2007]生成树计数 矩阵乘法+最小表示法+插头dp
BZOJ1190:[HNOI2007]梦幻岛宝珠 dp

BZOJ1493:[NOI2007]项链工厂 Splay

shinbokuow posted @ Mar 02, 2015 07:54:30 AM in BZOJ with tags Splay , 1183 阅读

思路:

脑补了半天发现还是不知道怎么上线段树,于是无脑Splay.

操作应该都非常容易实现吧.

对于每一个节点记录一下区间的左右端的颜色,自己的颜色以及颜色段数.

没什么好说的,详情见代码.

 

教训:

我得到区间是利用返回Splay中的一个点来实现的.

注意这个点并不是静态的.

所以得到之后立即将信息存下来.

否则再去得到别的区间的时候,这个点的信息会发生变化.

 

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
 
#define N 500010
 
#define l ch[0]
#define r ch[1]
 
int a[N];
struct Node{
    Node*ch[2],*pa;
    int siz,num,c,col,lcol,rcol;
    bool rev;
    Node():siz(0),num(0),rev(0){}
     
    bool d(){return this==pa->ch[1];}
    inline void sc(Node*p,bool d){ch[d]=p,p->pa=this;}
}mem[N],*P=mem,Tnull,*null=&Tnull,*Root;
 
inline void covit(Node*p,int c){
    p->c=p->col=p->lcol=p->rcol=c;
    p->num=1;
}
inline void revit(Node*p){
    p->rev^=1,swap(p->lcol,p->rcol),swap(p->l,p->r);
}
inline void down(Node*p){
    if(p->rev){
        if(p->l!=null)revit(p->l);
        if(p->r!=null)revit(p->r);
        p->rev=0;
    }
    if(p->c!=0){
        if(p->l!=null)covit(p->l,p->c);
        if(p->r!=null)covit(p->r,p->c);
        p->c=0;
    }
}
inline void up(Node*p){
    p->siz=p->l->siz+1+p->r->siz;
    p->num=p->l->num+p->r->num+1;
    if(p->l!=null&&p->col==p->l->rcol)--p->num;
    if(p->r!=null&&p->col==p->r->lcol)--p->num;
    p->lcol=(p->l!=null)?p->l->lcol:p->col;
    p->rcol=(p->r!=null)?p->r->rcol:p->col;
}
Node*Newnode(int col){
    P->l=P->r=P->pa=null;
    P->siz=1,P->num=1,P->c=P->rev=0,P->col=P->lcol=P->rcol=col;return P++;
}
Node*Build(int tl,int tr){
    if(tl>tr)return null;
    int mid=(tl+tr)>>1;
    Node*q=Newnode(a[mid]);
    q->sc(Build(tl,mid-1),0);
    q->sc(Build(mid+1,tr),1);
    up(q);
    return q;
}
inline void Rot(Node*p){
    bool d=p->d();Node*fa=p->pa;
    down(fa),down(p);
    fa->pa->sc(p,fa->d()),fa->sc(p->ch[!d],d),p->sc(fa,!d);
    up(fa);
    if(fa==Root)Root=p;
}
inline void Splay(Node*p,Node*Anc=null){
    while(p->pa!=Anc){
        if(p->pa->pa==Anc)Rot(p);
        else Rot(p->d()==p->pa->d()?p->pa:p),Rot(p);
    }up(p);
}
inline Node*kth(int k){
    Node*re=Root;
    while(1){
        down(re);
        if(re->l->siz>=k)re=re->l;
        else if(k==re->l->siz+1)return re;
        else k-=re->l->siz+1,re=re->r;
    }
}
inline Node*get(int dl,int dr){
    Node*p=kth(dl);Splay(p);
    Node*q=kth(dr+2);Splay(q,p);
    return q->l;
}
inline Node*del(int dl,int dr){
    Node*p=get(dl,dr);
    p->pa->sc(null,0),up(p->pa),up(p->pa->pa);
    return p;
}
inline void cover(int dl,int dr,int c){
    covit(get(dl,dr),c);
}
inline void reverse(int dl,int dr){
    revit(get(dl,dr));
}
inline void insert(int ins,Node*x){
    Node*p=kth(ins);Splay(p);
    Node*q=kth(ins+1);Splay(q,p);
    q->sc(x,0),up(q),up(p);
}
 
inline void pre(){
    Root=Newnode(0);
    Node*p=Newnode(0);
    Root->sc(p,1),up(Root);
}
 
int main(){
    int n,Maxc;scanf("%d%d",&n,&Maxc);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
     
    pre(),insert(1,Build(1,n));
     
    int m;
    scanf("%d",&m);
    char qte[10];int x,y,c;
    while(m--){
        scanf("%s",qte);
         
        if(qte[0]=='R'){
            scanf("%d",&x);
             
            Node*p=del(n-x+1,n);
            insert(1,p);
        }
         
        if(qte[0]=='F'){
            reverse(2,n);
        }
         
        if(qte[0]=='S'){
            scanf("%d%d",&x,&y);
            if(x!=y){
                 
                if(x>y)swap(x,y);
             
                Node*getx=del(x,x),*gety=del(y-1,y-1);
                insert(x,gety),insert(y,getx);
            }
        }
         
        if(qte[0]=='P'){
            scanf("%d%d%d",&x,&y,&c);
             
            if(x<=y)cover(x,y,c);
            else cover(x,n,c),cover(1,y,c);
        }
         
        if(strlen(qte)==1&&qte[0]=='C'){
            Node*re=get(1,n);
            printf("%d\n",re->num==1?1:re->num-(re->lcol==re->rcol));
        }
         
        if(qte[0]=='C'&&qte[1]=='S'){
            scanf("%d%d",&x,&y);
            if(x<=y){
                Node*re=get(x,y);
                printf("%d\n",re->num);
            }
            else{
                int re=0,rcol,lcol;
                Node*re1=get(x,n);re+=re1->num,rcol=re1->rcol;
                Node*re2=get(1,y);re+=re2->num,lcol=re2->lcol;
                printf("%d\n",re-(rcol==lcol));
            }
        }
    }
     
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter