【BZOJ2002】弹飞绵羊(LCT)

题意:给定一棵树,要求维护以下操作:

1.删除连接(x,y)的边

2.将(x,y)之间连边

3.询问某点子树大小

对于100%的数据n<=200000,m<=100000

思路:第一道有加边删边的LCT

讲一下自己对LCT各个操作的理解

Access:最基本的操作,将一个点到LCT的根的点全部修改为重(实)边

可以理解为“全选操作”,配合Splay操作可以取出某段区间的信息

Splay:将X旋转到它所在链的顶部,这样就相当于将这条链中的信息集中到了X这个点上

LCT的splay要用栈pushdown维护的原因是普通splay中splay操作前这些信息已经在Findkth的时候下传

而LCT没有,需要手动下传

Findroot:找到LCT的根,先Access+splay,因为LCT是按照深度维护的,所以一直往左走,找到深度最小的就是根

Makeroot:将X设置为LCT的根,Access+splay,因为上下翻转了所以要打翻转标记

Link:链接两个不在同一条链上的点,Makeroot(x),fa[x]=y

split:取出(x,y)这段区间的信息,Makeroot(x),Access(y),splay(y),信息在y点上

此题输出左儿子的子树大小即可

  1 var t:array[0..500000,0..1]of longint;
  2     next,fa,rev,size,q:array[0..500000]of longint;
  3     n,m,i,x,y,tmp,top:longint;
  4 
  5 function isroot(x:longint):boolean;
  6 begin
  7  if (t[fa[x],0]<>x)and(t[fa[x],1]<>x) then exit(true);
  8  exit(false);
  9 end;
 10 
 11 procedure swap(var x,y:longint);
 12 var t:longint;
 13 begin
 14  t:=x; x:=y; y:=t;
 15 end;
 16 
 17 procedure pushup(x:longint);
 18 var l,r:longint;
 19 begin
 20  l:=t[x,0]; r:=t[x,1];
 21  size[x]:=size[l]+size[r]+1;
 22 end;
 23 
 24 procedure pushdown(x:longint);
 25 var l,r:longint;
 26 begin
 27  l:=t[x,0]; r:=t[x,1];
 28  if rev[x]>0 then
 29  begin
 30   rev[x]:=rev[x] xor 1; rev[l]:=rev[l] xor 1; rev[r]:=rev[r] xor 1;
 31   swap(t[x,0],t[x,1]);
 32  end;
 33 end;
 34 
 35 procedure rotate(x:longint);
 36 var y,z,l,r:longint;
 37 begin
 38  y:=fa[x]; z:=fa[y];
 39  if t[y,0]=x then l:=0
 40   else l:=1;
 41  r:=l xor 1;
 42  while not isroot(y) do
 43  begin
 44   if t[z,0]=y then t[z,0]:=x
 45    else t[z,1]:=x;
 46  end;
 47  fa[x]:=z; fa[y]:=x; fa[t[x,r]]:=y;
 48  t[y,l]:=t[x,r]; t[x,r]:=y;
 49  pushup(y);
 50  pushup(x);
 51 end;
 52 
 53 procedure splay(x:longint);
 54 var y,z,k:longint;
 55 begin
 56  inc(top); q[top]:=x;
 57  k:=x;
 58  while not isroot(k) do
 59  begin
 60   inc(top); q[top]:=fa[k];
 61   k:=fa[k];
 62  end;
 63  while top>0 do
 64  begin
 65   pushdown(q[top]);
 66   dec(top);
 67  end;
 68 
 69  while not isroot(x) do
 70  begin
 71   y:=fa[x]; z:=fa[y];
 72   if not isroot(y) then
 73   begin
 74    if (t[y,0]=x)xor(t[z,0]=y) then rotate(x)
 75     else rotate(y);
 76   end;
 77   rotate(x);
 78  end;
 79 end;
 80 
 81 procedure access(x:longint);
 82 var last:longint;
 83 begin
 84  last:=0;
 85  while x>0 do
 86  begin
 87   splay(x); t[x,1]:=last; //pushup(x);
 88   last:=x; x:=fa[x];
 89  end;
 90 end;
 91 
 92 procedure makeroot(x:longint);
 93 begin
 94  access(x); splay(x); rev[x]:=rev[x] xor 1;
 95 end;
 96 
 97 procedure link(x,y:longint);
 98 begin
 99  makeroot(x); fa[x]:=y;
100 end;
101 
102 procedure split(x,y:longint);
103 begin
104  makeroot(x); access(y); splay(y);
105 end;
106 
107 procedure cut(x,y:longint);
108 begin
109  makeroot(x); access(y); splay(y); t[y,0]:=0; fa[x]:=0;
110 end;
111 
112 function min(x,y:longint):longint;
113 begin
114  if x<y then exit(x);
115  exit(y);
116 end;
117 
118 begin
119  assign(input,'bzoj2002.in'); reset(input);
120  assign(output,'bzoj2002.out'); rewrite(output);
121  readln(n);
122  for i:=1 to n do
123  begin
124   read(x);
125   fa[i]:=x+i; size[i]:=1;
126   if fa[i]>n then fa[i]:=n+1;
127   next[i]:=fa[i];
128  end;
129  size[n+1]:=1;
130  readln(m);
131  for i:=1 to m do
132  begin
133   read(x);
134   case x of
135    1:
136    begin
137     read(y); inc(y);
138     split(n+1,y);
139     writeln(size[t[y,0]]);
140    end;
141    2:
142    begin
143     read(x,y);
144     inc(x); tmp:=min(x+y,n+1);
145     cut(x,next[x]); link(x,tmp); next[x]:=tmp;
146    end;
147   end;
148  end;
149  close(input);
150  close(output);
151 end.

 

posted on 2017-01-18 16:20  myx12345  阅读(121)  评论(0编辑  收藏

导航