您的位置:首页 > 其它

[BZOJ1493][NOI2007]项链工厂

2016-03-22 19:11 507 查看
原题地址

又是一道数据结构神题,卡了一晚上…

写一下其中几个写搓的地方:

1.update()时要clear()左右子树

2.查询完之后要记得把树merge()回去

3.交换操作那里,若i,j相等则直接退出,要不然会出错

4.染色\查询操作L<=R和L>R时split()的范围不同

UPDATE:split()函数里是不需要用到merge()的!这样就可以实现空间O(n lg n)的可持久化了.以后都要按新的写法来写.

AC code:

#include <cstdio>
#include <cstdlib>
#include <ctime>
const int N=1000010;
int n,c,q,tot;
int a
;

struct nod{
int  c,lc,rc,sum,siz,tag,fix;
bool rev;
nod  *ch[2];
}*NIL,pool
;

struct Treap{
nod *root;

Treap(){
root=NIL=&pool[tot++];
for(int i=1;i<=n;i++) root=merge(root,newnod(a[i]));
}
nod* newnod(int c){
nod *p=&pool[tot++];
p->c=p->lc=p->rc=c;p->sum=p->siz=1;p->fix=rand()*rand()%N;
p->ch[0]=p->ch[1]=NIL;
return p;
}
void update(nod *p){
p->siz=p->ch[0]->siz+p->ch[1]->siz+1;p->lc=p->rc=p->c;p->sum=1;
clear(p->ch[0]);clear(p->ch[1]);
if(p->ch[0]!=NIL){
p->sum+=p->ch[0]->sum;
if(p->ch[0]->rc==p->c) p->sum--;
p->lc=p->ch[0]->lc;
}
if(p->ch[1]!=NIL){
p->sum+=p->ch[1]->sum;
if(p->ch[1]->lc==p->c) p->sum--;
p->rc=p->ch[1]->rc;
}
}
void clear(nod *p){
if(p==NIL) return ;
if(p->rev){
int tc=p->lc;p->lc=p->rc;p->rc=tc;
nod *tp=p->ch[0];p->ch[0]=p->ch[1];p->ch[1]=tp;
p->rev=0;p->ch[0]->rev^=1;p->ch[1]->rev^=1;
}
if(p->tag){
p->c=p->lc=p->rc=p->tag;p->sum=1;
p->ch[0]->tag=p->ch[1]->tag=p->tag;p->tag=0;
}
}
nod* merge(nod *p1,nod *p2){
clear(p1);clear(p2);
if(p1==NIL) return p2;
if(p2==NIL) return p1;
if(p1->fix<=p2->fix){
p2->ch[0]=merge(p1,p2->ch[0]);
update(p2);
return p2;
}
p1->ch[1]=merge(p1->ch[1],p2);
update(p1);
return p1;
}
void split(nod *p,nod *&p1,nod *&p2,int k){
clear(p);
if(p==NIL){
p1=p2=NIL;
return ;
}
if(p->ch[0]->siz+1<=k){
split(p->ch[1],p1,p2,k-p->ch[0]->siz-1);
p->ch[1]=p1;
update(p);
p1=p;
}
else{
split(p->ch[0],p1,p2,k);
p->ch[0]=p2;
update(p);
p2=p;
}
}
void work1(int k){
nod *p1,*p2;
split(root,p1,p2,n-k);
root=merge(p2,p1);
}
void work2(){
nod *p1,*p2;
split(root,p1,p2,1);
p2->rev^=1;
root=merge(p1,p2);
}
void work3(int L,int R){
if(L==R) return ;
if(L>R){int t=L;L=R;R=t;}
nod *p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8;
split(root,p1,p6,L-1);
split(p6,p2,p7,1);
split(p7,p3,p8,R-L-1);
split(p8,p4,p5,1);
root=merge(p1,merge(p4,merge(p3,merge(p2,p5))));
}
void work4(int L,int R,int k){
nod *p1,*p2,*p3,*p4;
if(L<=R){
split(root,p1,p4,L-1);
split(p4,p2,p3,R-L+1);
p2->tag=k;
}
else{
int t=L;L=R;R=t;
4000
split(root,p1,p4,L);
split(p4,p2,p3,R-L-1);
p1->tag=p3->tag=k;
}
root=merge(p1,merge(p2,p3));
}
int work5(){
clear(root);
if(root->sum==1) return 1;
int ans=work6(1,n);
if(root->lc==root->rc) ans--;
return ans;
}
int work6(int L,int R){
int ans;
nod *p1,*p2,*p3,*p4;
if(L<=R){
split(root,p1,p4,L-1);
split(p4,p2,p3,R-L+1);
clear(p2);
ans=p2->sum;
}
else{
int t=L;L=R;R=t;
split(root,p1,p4,L);
split(p4,p2,p3,R-L-1);
clear(p1);clear(p3);
ans=p1->sum+p3->sum;
if(p1->lc==p3->rc) ans--;
}
root=merge(p1,merge(p2,p3));
return ans;
}
};

int main(){
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
Treap T;
scanf("%d",&q);
for(int i=1;i<=q;i++){
int L,R,x;
char s[1<<2];
scanf("%s",s);
if(s[0]=='R'){
scanf("%d",&x);
T.work1(x);
}
else if(s[0]=='F') T.work2();
else if(s[0]=='S'){
scanf("%d%d",&L,&R);
T.work3(L,R);
}
else if(s[0]=='P'){
scanf("%d%d%d",&L,&R,&x);
T.work4(L,R,x);
}
else if(s[0]=='C'&&s[1]=='\0') printf("%d\n",T.work5());
else{
scanf("%d%d",&L,&R);
printf("%d\n",T.work6(L,R));
}
}

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