算法模板——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.
时间: 2024-10-20 09:20:25

算法模板——splay区间反转 2的相关文章

算法模板——splay区间反转

实现的功能:将序列区间反转,并维护 详见BZOJ3223 1 var 2 i,j,k,l,m,n,head,a1,a2:longint; 3 s1:ansistring; 4 a,b,c,d,fat,lef,rig:array[0..200000] of longint; 5 procedure swap(var x,y:longint);inline; 6 var z:longint; 7 begin 8 z:=x;x:=y;y:=z; 9 end; 10 11 procedure ext(x

Splay 区间反转

同样的,我们以一道题来引入. 传送门 这次的任务比较少,只要求进行区间反转.区间反转? 这个好像用啥都是O(n)的吧--(这次vector,set也救不了你了) 我们来使用splay解决这个问题.我们既然要反转一段区间,那我们肯定要把这个区间弄到一个地方.我们想一下上次所讲的删除操作,我们把要删除的数的前驱后继都找了出来并且一个旋转到根,一个到根的右儿子.我们思考一下发现,如果把这个区间第一个数的前一个数(l-1)旋转到根,把区间最后一个数的后一个数(r+1)旋转到根的右儿子,那么现在根的右儿子

hdu 1890 Robotic Sort(splay 区间反转+删点)

题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的splay区间翻转+删点. 我们把数据排序,然后记录一下每个数原来的位置,然后splay建树的时候用原来的位置来对应,这样val[i].second就直接是这个数在splay中的那个节点. (当然你也可以普通建树,然后手动记录位置). 然后我们把要找的那个数对应的节点旋转到根,然后根左边的size+i就

[bzoj3223]文艺平衡树(splay区间反转模板)

解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int N = 100005; int ch[N][2],par[N],val[N],cnt[

HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratories for examining

hdu1890 伸展树(区间反转)

对于大神来说这题是水题.我搞这题花了快2天. 伸展树的优点有什么,就是树不管你怎么旋转序列是不会改变得,并且你要使区间反转,只要把第k大的点转到根结点,那么它的左子树就是要交换的区间[l,r),然后交换左右 子树就可以了(中序),根结点的位置就是i+siz[ch[root][0]],i是处理完的结点个数,siz[ch[root][0]]就是左子树(需要旋转的个数). 旋转可以用lazy思想标记,这样时间就为logn了.由于第k大的值已经处理完成,所以直接将根结点删除. 代码: #include<

HDU 1890 Robotic Sort 伸展树的区间反转与延迟标记

延迟标记像极了线段树,不再多说. 区间反转在树伸展到位之后,也变成了简单的递归交换左右儿子. 愈发感觉到伸展树简直太漂亮了,伸展操作更是诱惑到不行 ,总之数据结构太有魅力了. 比较简单,就直接上模板了. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #in

二分——二分查找算法模板

转自:二分查找算法模板 二分模板一共有两个,分别适用于不同情况.算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值. 版本1当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1. C++ 代码模板: int bsearch_1(int l, int r) { while (l < r) { int mid = l + r >> 1;

[算法模板]FFT-快速傅里叶变换

[算法模板]FFT-快速傅里叶变换 感谢ZYW聚聚为我们讲解FFT~ 思路 我懒,思路和证明部分直接贴链接: rvalue LSJ-FFT与NTT基础 代码 主要思想是利用了单位根特殊的性质(n次单位根后一半幂跟前一半幂取值相等).只是因为式子中奇数次幂还要提出来个\(\omega_n^k\),这个东西只要取个反就好了(即对称性:\(\omega_n^k=-\omega_n^{k+\frac{n}{2}}\)). FFT递归: #include <cstdio> #include <cm