[BZOJ1493][NOI2007]项链工厂
来源:互联网 发布:web微信开发工具linux 编辑:程序博客网 时间:2024/05/18 04:59
原题地址
又是一道数据结构神题,卡了一晚上…
写一下其中几个写搓的地方:
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[N];struct nod{ int c,lc,rc,sum,siz,tag,fix; bool rev; nod *ch[2]; }*NIL,pool[N];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; 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;}
0 0
- [BZOJ1493][NOI2007]项链工厂
- bzoj1493: [NOI2007]项链工厂
- bzoj1493: [NOI2007]项链工厂 splay
- BZOJ1493: [NOI2007]项链工厂 Splay
- [题解]bzoj1493 NOI2007项链工厂
- [BZOJ1493][NOI2007]项链工厂(splay)
- [bzoj1493]1493: [NOI2007]项链工厂 线段树
- 【bzoj1493】项链工厂【线段树】
- 1493: [NOI2007]项链工厂
- 【线段树】【NOI2007】项链工厂
- 【BZOJ 1493】[NOI2007]项链工厂
- 【BZOJ】1493 [NOI2007]项链工厂 线段树
- BZOJ 1493 NOI2007 项链工厂 Splay
- 【BZOJ】【P1493】【NOI2007】【项链工厂】【题解】【Treap】
- [NOI2007]项链工厂(线段树)
- bzoj 1493 [NOI2007]项链工厂 线段树
- [BZOJ]1493 [NOI2007]项链工厂 线段树
- bzoj 1493: [NOI2007]项链工厂 (平衡树)
- 使用VC++绘制坐标系
- JXL操作Excel
- WorkBench插入中文数据??问题
- PKIX path building failed
- solr入门之搜索建议的几种实现方式和最终选取实现思路
- [BZOJ1493][NOI2007]项链工厂
- 输出星号图案
- 开通博客第一天
- ubuntu 14.04 无线网连接一会儿后, wifi 没掉, 但不能上网的解决方案
- 监听scroollview、listview、gridview页面滑动,判断是否滑动到顶部以及底部
- 欢迎使用CSDN-markdown编辑器
- [积累]CSS手册
- 计算一年有多少天
- hdu 5317 RGCDQ (dp+筛法)