算法模板——splay区间反转 2

时间:2022-05-08
本文章向大家介绍算法模板——splay区间反转 2,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树)

这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善

这里面没有像一般二叉排序树那样子用一个参量进行排序,而是直接以中序遍历来构建了一个普通的二叉树(当然也可以把每个点的中序遍历排名视作参量),然后插入的时候就是指定位置插入(这个就比较像是文本插入了)

总之得到了较大的提升,代码优美程度也提高不少

  1 var
  2    i,j,k,l,m,n,head,tot,ll:longint;
  3    a,lef,rig,b,c:array[0..100000] of longint;
  4 procedure swap(var x,y:longint);
  5           var z:longint;
  6           begin
  7                z:=x;x:=y;y:=z;
  8           end;
  9 procedure ext(x:longint);  //经典的下推操作,有木有很像线段树呢= =
 10           begin
 11                if x=0 then exit;
 12                if c[x]=0 then exit;
 13                if lef[x]<>0 then c[lef[x]]:=1-c[lef[x]];
 14                if rig[x]<>0 then c[rig[x]]:=1-c[rig[x]];
 15                swap(lef[x],rig[x]);
 16                c[x]:=0;
 17           end;
 18 procedure rt(var x:longint);  //lt、rt函数和Treap的极其相似!!!
 19           var f,l:longint;
 20           begin
 21                ext(x);ext(lef[x]);
 22                if (x=0) or (lef[x]=0) then exit;
 23                f:=x;l:=lef[x];
 24                b[lef[x]]:=b[x];
 25                b[x]:=1+b[rig[x]]+b[rig[lef[x]]];
 26                lef[f]:=rig[l];
 27                rig[l]:=f;
 28                x:=l;
 29           end;
 30 procedure lt(var x:longint);
 31           var f,r:longint;
 32           begin
 33                ext(x);ext(rig[x]);
 34                if (x=0) or (rig[x]=0) then exit;
 35                f:=x;r:=rig[x];
 36                b[rig[x]]:=b[x];
 37                b[x]:=1+b[lef[x]]+b[lef[rig[x]]];
 38                rig[f]:=lef[r];
 39                lef[r]:=f;
 40                x:=r;
 41           end;
 42 procedure splay(var head:longint;x:longint);   //萌萌哒伸展——而且还可以支持伸展的任意位置,只要设定head的位置,比如像后面的splay(rig[head],x);
 43           begin
 44                if head=0 then exit;
 45                ext(head);
 46                if (b[lef[head]]+1)=x then exit;
 47                if x<(b[lef[head]]+1) then
 48                   begin
 49                        ext(lef[head]);
 50                        if x=(b[lef[lef[head]]]+1) then rt(head) else
 51                           if x<(b[lef[lef[head]]]+1) then
 52                              begin
 53                                   splay(lef[lef[head]],x);
 54                                   rt(head);rt(head);
 55                              end
 56                           else
 57                               begin
 58                                    splay(rig[lef[head]],x-1-b[lef[lef[head]]]);
 59                                    lt(lef[head]);rt(head);
 60                               end;
 61                   end
 62                else
 63                    begin
 64                         ext(rig[head]);
 65                         x:=x-1-b[lef[head]];
 66                         if x=(b[lef[rig[head]]]+1) then lt(head) else
 67                            if x<(b[lef[rig[head]]]+1) then
 68                               begin
 69                                    splay(lef[rig[head]],x);
 70                                    rt(rig[head]);lt(head);
 71                               end
 72                            else
 73                                begin
 74                                     splay(rig[rig[head]],x-1-b[lef[rig[head]]]);
 75                                     lt(head);lt(head);
 76                                end;
 77                    end;
 78           end;
 79 procedure ins(x,y:longint);  //这里的ins操作已经可以支持指定位置插入子伸展树了
 80           begin
 81                if head=0 then
 82                   begin
 83                        head:=y;
 84                        exit;
 85                   end;
 86                if x=b[head] then
 87                   begin
 88                        splay(head,b[head]);
 89                        rig[head]:=y;
 90                        inc(b[head],b[y]);
 91                   end
 92                else if x=0 then
 93                     begin
 94                          splay(head,1);
 95                          lef[head]:=y;
 96                          inc(b[head],b[y]);
 97                     end
 98                else begin
 99                     splay(head,x);
100                     splay(rig[head],x+1);
101                     lef[rig[head]]:=y;
102                     inc(b[rig[head]],b[y]);
103                     inc(b[head],b[y]);
104                end;
105           end;
106 procedure putinvalue(x,y:longint);  //加入单个值
107          begin
108               inc(tot);
109               A[TOT]:=x;b[tot]:=1;
110               lef[tot]:=0;rig[tot]:=0;
111               ins(y,tot);
112          end;
113  
114 procedure turnover(x,y:longint);  //翻转,核心思想还是打标记
115           begin
116                if x=y then exit;
117                if (x=1) and (y=n) then
118                   begin
119                        c[head]:=1-c[head];
120                        exit;
121                   end;
122                if (x=1) then
123                   begin
124                        splay(head,y+1);
125                        c[lef[head]]:=1-c[lef[head]];
126                   end
127                else if (y=n) then
128                     begin
129                          splay(head,x-1);
130                          c[rig[head]]:=1-c[rig[head]];
131                     end
132                else begin
133                     splay(head,x-1);
134                     splay(rig[head],y-x+2);
135                     c[lef[rig[head]]]:=1-c[lef[rig[head]]];
136                end;
137           end;
138 function showtree(head:longint):ansistring;
139          var s1,s2,s3,s4:ansistring;
140          begin
141               if head=0 then exit('');
142               str(a[head],s1);
143               s2:=showtree(lef[head]);
144               s3:=showtree(rig[head]);
145               if c[head]=1 then
146                  begin
147                       s4:=s2;
148                       s2:=s3;
149                       s3:=s4;
150                  end;
151               if s3<>'' then s3:=','+s3;
152               s2:=s2+s3;
153               if s2<>'' then s2:='('+s2+')';
154               exit(s1+s2);
155          end;
156 procedure putout(x:longint);
157           begin
158                if x=0 then exit;
159                ext(x);
160                putout(lef[x]);
161                write(a[x],' ');
162                putout(rig[x]);
163           end;
164 begin
165      readln(n,m);head:=0;tot:=0;
166      for i:=1 to n do putinvalue(i,i-1);
167      fillchar(c,sizeof(c),0);
168      for i:=1 to m do
169          begin
170               readln(j,k);
171               turnover(j,k);
172               l:=0;
173  
174          end;
175      putout(head);
176      writeln;
177      readln;
178 end.