题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
--by洛谷
http://daniu.luogu.org/problem/show?pid=3391
裸的平衡树反转;
方法是按序列位置为关键字排序;
反转(l,r):
则将l-1置于根处,将r+1作为根的右儿子,这样,r+1的左子树就是需要反转的区间;
然后对r+1的左儿子,反转其左右儿子,并打上线段树一样的lazy标记,待以后反转她的子树;
一开始,企图把位置维护为关键字,然后排序;
这样,
若点A为父节点的左儿子,则key[A]=key[fa[A]]-size[rs[A]]-1;
若点A为父节点的右儿子,则key[A]=key[fa[A]]+size[ls[A]]+1;
然后查找直接按查询关键字的方法找,十分方便;
然而关键字是时时变化的,不好维护,
另一种方法是直接在初次建好树后就再也不考虑维护关键字的问题,
直接按第K大的方法搜索,(从某种意义上讲她早已不是一般意义上的查找树了)
怎么办,选哪种方法继续呢?
一个很好的方法是把两个都写出来,
反正差不多
多好啊,还能对拍,是吧
代码如下:
1 #include<cstdio> 2 using namespace std; 3 int n,m; 4 struct dt{ 5 int cnt,size,key,lz; 6 int ch[2],fa; 7 }; 8 struct Splay{ 9 int root,tot; 10 dt data[100010]; 11 void in(){ 12 root=tot=0; 13 data[0].fa=data[0].cnt=data[0].size=data[0].key=0; 14 } 15 void splay(int x,int end){ 16 int fa,fafa; 17 for(fa=data[x].fa;(fa=data[x].fa)!=end;roll(x)){ 18 fafa=data[fa].fa; 19 if(fafa!=end){ 20 if((data[fafa].ch[1]==fa)^(data[fa].ch[1]==x)) 21 roll(x); 22 else 23 roll(fa); 24 } 25 } 26 if(!end) 27 root=x; 28 } 29 void roll(int x){ 30 int fa=data[x].fa,fafa=data[fa].fa; 31 int wh=data[fa].ch[1]==x; 32 data[fa].ch[wh]=data[x].ch[wh^1];data[data[x].ch[wh^1]].fa=fa; 33 data[x].ch[wh^1]=fa;data[fa].fa=x; 34 if(fafa) 35 data[fafa].ch[data[fafa].ch[1]==fa]=x; 36 data[x].fa=fafa; 37 up(fa);up(x); 38 } 39 void up(int x){ 40 data[x].size=data[data[x].ch[0]].size+data[data[x].ch[1]].size+1; 41 } 42 void buil_splay(int l,int r,int&nu,int fa){ 43 int mid=(l+r)>>1; 44 nu=++tot; 45 data[nu].key=mid; 46 data[nu].fa=fa; 47 data[nu].cnt=data[nu].size=1; 48 if(l==r)return; 49 if(l<mid) 50 buil_splay(l,mid-1,data[nu].ch[0],nu); 51 if(r>mid) 52 buil_splay(mid+1,r,data[nu].ch[1],nu); 53 data[nu].size=data[data[nu].ch[0]].size+data[data[nu].ch[1]].size+1; 54 } 55 int find(int x){ 56 int i=root; 57 while(!(data[data[i].ch[0]].size<x&&x<=data[i].size-data[data[i].ch[1]].size)){ 58 if(data[i].lz){ 59 change(data[i].ch[0]); 60 change(data[i].ch[1]); 61 data[i].lz=0; 62 } 63 if(x<=data[data[i].ch[0]].size) 64 i=data[i].ch[0]; 65 else{ 66 x-=(data[i].size-data[data[i].ch[1]].size); 67 i=data[i].ch[1]; 68 } 69 } 70 if(data[i].lz){ 71 change(data[i].ch[0]); 72 change(data[i].ch[1]); 73 data[i].lz=0; 74 } 75 return i; 76 } 77 void change(int x){ 78 int fa=data[x].fa,i; 79 i=data[x].ch[0];data[x].ch[0]=data[x].ch[1];data[x].ch[1]=i; 80 data[x].lz^=1; 81 } 82 void print(int now){ 83 if(data[now].lz){ 84 change(data[now].ch[0]); 85 change(data[now].ch[1]); 86 data[now].lz=0; 87 } 88 if(data[now].ch[0]) 89 print(data[now].ch[0]); 90 if(data[now].key!=0&&data[now].key!=n+1) 91 printf("%d ",data[now].key); 92 if(data[now].ch[1]) 93 print(data[now].ch[1]); 94 } 95 }; 96 Splay splay; 97 int main() 98 { 99 int i,j,k,l; 100 scanf("%d%d",&n,&m); 101 splay.buil_splay(0,n+1,splay.root,0); 102 for(i=1;i<=m;i++){ 103 scanf("%d%d",&j,&k); 104 if(j==k)continue; 105 l=splay.find(j); 106 splay.splay(l,0); 107 l=splay.find(k+2); 108 splay.splay(l,splay.root); 109 splay.change(splay.data[splay.data[splay.root].ch[1]].ch[0]); 110 } 111 splay.print(splay.root); 112 }
1 #include<cstdio> 2 using namespace std; 3 int n,m; 4 struct dt{ 5 int value,cnt,size,key,lz; 6 int ch[2],fa; 7 }; 8 struct Splay{ 9 int root,tot; 10 dt data[100010]; 11 void in(){ 12 root=tot=0; 13 data[0].fa=data[0].cnt=data[0].size=data[0].value=data[0].key=0; 14 } 15 void splay(int x,int end){ 16 int fa,fafa; 17 for(fa=data[x].fa;(fa=data[x].fa)!=end;roll(x)){ 18 fafa=data[fa].fa; 19 if(fafa!=end){ 20 if((data[fafa].ch[1]==fa)^(data[fa].ch[1]==x)) 21 roll(x); 22 else 23 roll(fa); 24 } 25 } 26 if(!end) 27 root=x; 28 } 29 void roll(int x){ 30 int fa=data[x].fa,fafa=data[fa].fa; 31 int wh=data[fa].ch[1]==x; 32 data[fa].ch[wh]=data[x].ch[wh^1];data[data[x].ch[wh^1]].fa=fa; 33 data[x].ch[wh^1]=fa;data[fa].fa=x; 34 if(fafa) 35 data[fafa].ch[data[fafa].ch[1]==fa]=x; 36 data[x].fa=fafa; 37 up(fa);up(x); 38 } 39 void up(int x){ 40 data[x].size=data[data[x].ch[0]].size+data[data[x].ch[1]].size+1; 41 } 42 void buil_splay(int l,int r,int&nu,int fa){ 43 int mid=(l+r)>>1; 44 nu=++tot; 45 data[nu].value=data[nu].key=mid; 46 data[nu].fa=fa; 47 data[nu].cnt=data[nu].size=1; 48 if(l==r)return; 49 if(l<mid) 50 buil_splay(l,mid-1,data[nu].ch[0],nu); 51 if(r>mid) 52 buil_splay(mid+1,r,data[nu].ch[1],nu); 53 data[nu].size=data[data[nu].ch[0]].size+data[data[nu].ch[1]].size+1; 54 } 55 int find(int x){ 56 int i=root; 57 while(1){ 58 change(data[i].ch[0]); 59 change(data[i].ch[1]); 60 data[i].lz=0; 61 if(data[i].value==x) 62 break; 63 i=data[i].ch[data[i].value<x]; 64 } 65 return i; 66 } 67 void change(int x){ 68 int fa=data[x].fa,i; 69 if(data[fa].lz){ 70 i=data[x].ch[0];data[x].ch[0]=data[x].ch[1];data[x].ch[1]=i; 71 data[x].lz^=1; 72 } 73 if(data[fa].ch[0]==x) 74 data[x].value=data[fa].value-data[data[x].ch[1]].size-1; 75 else 76 data[x].value=data[fa].value+data[data[x].ch[0]].size+1; 77 } 78 void print(int now){ 79 change(data[now].ch[0]); 80 change(data[now].ch[1]); 81 data[now].lz=0; 82 if(data[now].ch[0]) 83 print(data[now].ch[0]); 84 if(data[now].key!=0&&data[now].key!=n+1) 85 printf("%d ",data[now].key); 86 if(data[now].ch[1]) 87 print(data[now].ch[1]); 88 } 89 }; 90 Splay splay; 91 int main() 92 { 93 int i,j,k,l; 94 scanf("%d%d",&n,&m); 95 splay.buil_splay(0,n+1,splay.root,0); 96 for(i=1;i<=m;i++){ 97 scanf("%d%d",&j,&k); 98 if(j==k)continue; 99 l=splay.find(j-1); 100 splay.splay(l,0); 101 l=splay.find(k+1); 102 splay.splay(l,splay.root); 103 splay.data[splay.data[splay.root].ch[1]].lz=1; 104 splay.change(splay.data[splay.data[splay.root].ch[1]].ch[0]); 105 splay.data[splay.data[splay.root].ch[1]].lz=0; 106 } 107 splay.print(splay.root); 108 }
祝AC