算法模板——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:longint);inline;
 12           begin
 13                if (x=0) then exit;
 14                if c[x]=0 then exit;
 15                swap(lef[x],rig[x]);
 16                c[x]:=0;
 17                c[lef[x]]:=1-c[lef[x]];
 18                c[rig[x]]:=1-c[rig[x]];
 19                c[0]:=0;
 20           end;
 21 procedure rt(x:longint);inline;
 22           var f,l:longint;
 23           begin
 24                if x=0 then exit;
 25                ext(x);
 26                if lef[x]=0 then exit;
 27                ext(lef[x]);
 28                f:=x;l:=lef[x];
 29                b[lef[x]]:=b[x];
 30                b[x]:=b[rig[x]]+1+b[rig[l]];
 31                lef[x]:=rig[l];
 32                fat[rig[l]]:=x;
 33                rig[l]:=x;
 34                fat[l]:=fat[x];
 35                fat[x]:=l;
 36                if rig[fat[l]]=x then rig[fat[l]]:=l;
 37                if lef[fat[l]]=x then lef[fat[l]]:=l;
 38                fat[0]:=0;
 39           end;
 40 procedure lt(x:longint);inline;
 41           var f,r:longint;
 42           begin
 43                if x=0 then exit;
 44                ext(x);if rig[x]=0 then exit;
 45                ext(rig[x]);
 46                f:=x;r:=rig[x];
 47                b[rig[x]]:=b[x];
 48                b[x]:=1+b[lef[x]]+b[lef[r]];
 49                rig[x]:=lef[r];
 50                fat[lef[r]]:=x;
 51                lef[r]:=x;
 52                fat[r]:=fat[x];
 53                fat[x]:=r;
 54                if rig[fat[r]]=x then rig[fat[r]]:=r;
 55                if lef[fat[r]]=x then lef[fat[r]]:=r;
 56                fat[0]:=0;
 57           end;
 58 procedure ins(x,y:longint);inline;
 59           begin
 60                if a[y]<a[x] then
 61                   begin
 62                        if lef[x]=0 then
 63                           begin
 64                                lef[x]:=y;
 65                                fat[y]:=x;
 66                           end
 67                        else ins(lef[x],y);
 68                   end
 69                else
 70                    begin
 71                         if rig[x]=0 then
 72                            begin
 73                                 rig[x]:=y;
 74                                 fat[y]:=x;
 75                            end
 76                         else ins(rig[x],y);
 77                    end;
 78                b[x]:=1+b[lef[x]]+b[rig[x]];
 79           end;
 80 procedure up2(var x:longint);inline;
 81           begin
 82                if (fat[x]=0) or (x=0) then exit;
 83                if lef[fat[x]]=x then
 84                   begin
 85                        if lef[fat[fat[x]]]=fat[x] then
 86                           begin
 87                                rt(fat[fat[x]]);
 88                                rt(fat[x]);
 89                           end
 90                        else
 91                            begin
 92                                 rt(fat[x]);
 93                                 lt(fat[x]);
 94                            end;
 95                   end
 96                else
 97                    begin
 98                         if rig[fat[fat[x]]]=fat[x] then
 99                            begin
100                                 lt(fat[fat[x]]);
101                                 lt(fat[x]);
102                            end
103                         else
104                             begin
105                                  lt(fat[x]);
106                                  rt(fat[x]);
107                             end;
108                    end;
109           end;
110 procedure up1(x:longint);inline;
111           begin
112                if (x=0) or (fat[x]=0) then exit;
113                if lef[fat[x]]=x then rt(fat[x]) else lt(fat[x]);
114           end;
115 procedure splay(x:longint);inline;
116           begin
117                if (x=0) or (fat[x]=0) then exit;
118                while fat[fat[x]]>0 do
119                      up2(x);
120                if fat[x]>0 then up2(x);
121                head:=x;
122           end;
123 procedure splay2(x:longint);inline;
124           begin
125                if (x=0) or (fat[x]=0) then exit;
126                while fat[fat[fat[x]]]>0 do
127                      up2(x);
128                if fat[fat[x]]>0 then up1(x);
129           end;
130 function getrank(x,y:longint):longint;inline;
131          begin
132               if (x=0) then exit(0);
133               ext(x);
134               if (b[lef[x]]+1)=y then exit(x);
135               if (b[lef[x]]+1)>y then exit(getrank(lef[x],y)) else exit(getrank(rig[x],y-1-b[lef[x]]));
136          end;
137 procedure turn(x,y:longint);inline;
138           var a1,a2:longint;
139           begin
140                if (x=1) and (y=n) then
141                   c[head]:=1-c[head]
142                else
143                    begin
144                         if (x=1) then
145                            begin
146                                 a1:=getrank(head,y+1);
147                                 splay(a1);
148                                 ext(a1);
149                                 c[lef[a1]]:=1-c[lef[a1]];
150                            end
151                         else
152                             begin
153                                  if (y=n) then
154                                     begin
155                                          a2:=getrank(head,x-1);
156                                          splay(a2);
157                                          ext(a2);
158                                          c[rig[a2]]:=1-c[rig[a2]];
159                                     end
160                                  else
161                                      begin
162                                           a1:=getrank(head,x-1);
163                                           a2:=getrank(head,y+1);
164                                           splay(a2);splay2(a1);
165                                           ext(a2);ext(a1);
166                                           c[rig[a1]]:=1-c[rig[a1]];
167                                      end;
168                             end;
169                    end;
170           end;
171 function showoff(x:longint):ansistring;inline;
172          var s1:ansistring;
173          begin
174               if x=0 then exit(‘‘);
175               ext(x);
176               str(x,s1);
177               exit(showoff(lef[x])+s1+‘ ‘+showoff(rig[x]));
178          end;
179 begin
180      readln(n,m);
181      for i:=1 to n do
182          begin
183               a[i]:=i;c[i]:=0;b[i]:=1;
184          end;
185      head:=1;
186      for i:=2 to n do
187          begin
188               ins(head,i);
189               splay(random(i)+1);
190          end;
191      for i:=1 to m do
192          begin
193               readln(a1,a2);
194               turn(a1,a2);
195          end;
196      s1:=showoff(head);
197      writeln(s1);
198      readln;
199 end.
200                   
时间: 2024-10-23 13:51:20

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

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

实现功能:同splay区间反转 1(基于BZOJ3223 文艺平衡树) 这次改用了一个全新的模板(HansBug:琢磨了我大半天啊有木有),大大简化了程序,同时对于splay的功能也有所完善 这里面没有像一般二叉排序树那样子用一个参量进行排序,而是直接以中序遍历来构建了一个普通的二叉树(当然也可以把每个点的中序遍历排名视作参量),然后插入的时候就是指定位置插入(这个就比较像是文本插入了) 总之得到了较大的提升,代码优美程度也提高不少 1 var 2 i,j,k,l,m,n,head,tot,ll

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