很久没写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.