洛谷 P3391 文艺平衡树

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是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 }
View Code

  

  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 }
another_way

祝AC

 

posted @ 2017-04-06 14:33  F.W.Nietzsche  阅读(156)  评论(0编辑  收藏  举报