bzoj3223

很久没写splay了,这是用splay解决动态区间问题
平常splay树的建立都是以键值建立的
而这里是以位置序号为优先级建立的
不难发现,tree上的点代表的位置就是它的名次
splay的区间操作最重要的一点就是提取区间
设提取区间[a,b],则我们只要代表位置a-1的点伸展到根,再把代表位置b+1的点伸展到根的子树(显然在右子树)
然后显然,b+1的左子树就表示区间[a,b]
为了方便提取,我们常常会加入额外位置点0,n+1
这道题比较简单,只有翻转操作
显然这个是可以打标记的,每个点节点打上当前以这个点为根的子树是否要翻转
我们先提取区间,然后在根节点节点打上标记,显然这就表示这个区间要翻转
然后在之后的splay操作中维护这个标记即可

  1 var son:array[-1..100010,1..2] of longint;
  2     count,fa,a,b:array[-1..100010] of longint;
  3     v:array[-1..100010] of boolean;
  4     i,n,m,t,root,x,y:longint;
  5 
  6 procedure swap(var a,b:longint);
  7   var c:longint;
  8   begin
  9     c:=a;
 10     a:=b;
 11     b:=c;
 12   end;
 13 
 14 procedure change(x:longint);
 15   begin
 16     if x=-1 then exit;
 17     swap(son[x,1],son[x,2]);
 18     v[x]:=not v[x];
 19   end;
 20 
 21 procedure push(x:longint);
 22   begin
 23     if v[x] then
 24     begin
 25       change(son[x,1]);
 26       change(son[x,2]);
 27       v[x]:=false;
 28     end;
 29   end;
 30 
 31 procedure update(x:longint);
 32   begin
 33     count[x]:=count[son[x,1]]+count[son[x,2]]+1;
 34   end;
 35 
 36 procedure rotate(x,w:longint);
 37   var y:longint;
 38   begin
 39     push(x);
 40     y:=fa[x];
 41     if fa[y]<>-1 then
 42     begin
 43       if son[fa[y],1]=y then son[fa[y],1]:=x
 44       else son[fa[y],2]:=x;
 45     end;
 46     fa[x]:=fa[y];
 47     son[y,3-w]:=son[x,w];
 48     if son[x,w]<>-1 then fa[son[x,w]]:=y;
 49     son[x,w]:=y;
 50     fa[y]:=x;
 51     update(y);
 52     update(x);
 53   end;
 54 
 55 procedure splay(x,f:longint);
 56   var y:longint;
 57   begin
 58     while fa[x]<>f do
 59     begin
 60       y:=fa[x];
 61       if fa[y]=f then
 62       begin
 63         if son[y,1]=x then rotate(x,2)
 64         else rotate(x,1);
 65       end
 66       else begin
 67         if son[fa[y],1]=y then
 68         begin
 69           if son[y,1]=x then rotate(y,2) else rotate(x,1);
 70           rotate(x,2);
 71         end
 72         else begin
 73           if son[y,1]=x then rotate(x,2) else rotate(y,1);
 74           rotate(x,1);
 75         end;
 76       end;
 77     end;
 78     if f=-1 then root:=x;
 79   end;
 80 
 81 function build(l,r:longint):longint;
 82   var m:longint;
 83   begin
 84     m:=(l+r) shr 1;
 85     build:=m;
 86     if l<=m-1 then
 87     begin
 88       son[m,1]:=build(l,m-1);
 89       fa[son[m,1]]:=m;
 90     end;
 91     if m+1<=r then
 92     begin
 93       son[m,2]:=build(m+1,r);
 94       fa[son[m,2]]:=m;
 95     end;
 96     update(m);
 97   end;
 98 
 99 function find(k:longint):longint;
100   var p:longint;
101   begin
102     p:=root;
103     while true do
104     begin
105       push(p);
106       if count[son[p,1]]+1=k then exit(p)
107       else if count[son[p,1]]+1>k then p:=son[p,1]
108       else begin
109         k:=k-count[son[p,1]]-1;
110         p:=son[p,2];
111       end;
112     end;
113   end;
114 
115 procedure work(x,y:longint);
116   begin
117     x:=find(x);
118     y:=find(y+2);
119     splay(x,-1);
120     splay(y,x);
121     change(son[y,1]);
122   end;
123 
124 procedure mid(x:longint);
125   begin
126     push(x);
127     if son[x,1]<>-1 then mid(son[x,1]);
128     inc(t);
129     b[t]:=a[x];
130     if son[x,2]<>-1 then mid(son[x,2]);
131   end;
132 
133 begin
134   fillchar(son,sizeof(son),255);
135   fillchar(fa,sizeof(fa),255);
136   readln(n,m);
137   for i:=0 to n+1 do
138     a[i]:=i;
139   root:=build(0,n+1);  //先直接建立一棵平衡的BST
140   for i:=1 to m do
141   begin
142     readln(x,y);
143     work(x,y);
144   end;
145   t:=-1;
146   mid(root);
147   for i:=1 to t-1 do
148     write(b[i],' ');
149 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473040.html