带标记非递归的动态树

有时候splay如果需要带标记的话会必须递归从上至下的释放标记,这里是一个比较漂亮的非递归版本,为了优化常数。

以后他就是模板了吧,我可是苦苦调了一天才把所有细节扣了出的。。。

 

某题:

program t4;{$inline+} const o=50001; var root:array[0..o] of boolean; l,r,f,c,z,s,fa:array[0..o] of longint; i,q,g,t,n,m,x,y,cl,ans:longint; procedure put(i,cl:longint);inline; begin if (cl=0)or(i=o) then exit;z[i]:=cl;c[i]:=cl;f[i]:=1<<cl end; procedure lazy(i:longint);inline; begin put(l[i],z[i]);put(r[i],z[i]);z[i]:=0 end; procedure update(i:longint);inline; begin s[i]:=s[l[i]]+s[r[i]]+1; f[i]:=f[l[i]] or f[r[i]] or 1<<c[i]; end; procedure rt(i:longint;k:boolean);inline;var j:longint; begin if k then begin j:=r[i];r[i]:=l[j];fa[l[j]]:=i;l[j]:=i; end else begin j:=l[i];l[i]:=r[j];fa[r[j]]:=i;r[j]:=i; end; root[j]:=root[i];root[i]:=false; if l[fa[i]]=i then l[fa[i]]:=j else if r[fa[i]]=i then r[fa[i]]:=j; fa[j]:=fa[i];fa[i]:=j; update(i);update(j); end; procedure splay(i,k:longint);inline;var ff:longint; begin if root[i] then lazy(i); while not root[i] do begin ff:=fa[i]; lazy(ff); lazy(i); rt(ff,r[ff]=i); end; if k=1 then begin root[r[i]]:=true; g:=r[i];r[i]:=o; update(i); end; end; procedure access(i:longint); begin splay(i,1);t:=i; while fa[i]<>o do begin t:=fa[i];splay(t,1); r[t]:=i;rt(t,true); end; end; begin readln(n,m); fa[0]:=o; for i:=0 to n do root[i]:=true; for i:=1 to n do read(fa[i]); for i:=1 to n do read(c[i]); for i:=0 to n do update(i); for i:=0 to n do l[i]:=o; for i:=0 to n do r[i]:=o; for m:=1 to m do begin if m mod 6=0 then access(random(n+1)); readln;read(q,x,y); if q=1 then begin access(y);splay(x,0); if (r[x]=y)or(x=y) then continue; root[l[x]]:=true; fa[l[x]]:=fa[x]; fa[x]:=y;l[x]:=o; read(c[x]); update(x); end else if q=2 then begin access(x);access(y); if t=0 then continue; read(cl);splay(t,0); put(r[t],cl); update(t); put(g,cl); end else begin access(x);access(y); if t=0 then begin writeln('0 0'); continue; end; ans:=0;splay(t,0); for i:=1 to 30 do inc(ans,(f[g] or f[r[t]])>>i and 1); writeln(s[g]+s[r[t]],' ',ans); end; end; end. 

你可能感兴趣的:(c,优化,Random,Access)