您的位置:首页 > 其它

BZOJ 1493 项链工厂(splay)

2013-12-04 18:17 295 查看
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1493

题意:







思路:(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
,*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
;

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));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: