bzoj3123

时间:2023-03-10 01:40:23
bzoj3123

首先肯定是主席树
但这是一类“动态树”,似乎没有什么好的办法
那就暴力呗,这里用到启发式合并,即两棵树合并,重建节点少的的那棵
可以用并查集维护连通性
查询主席树的建立还是和bzoj2588一样

 const maxn=;
type node=record
po,next:longint;
end;
point=record
l,r,s:longint;
end; var tree:array[..maxn*] of point;
w:array[..*maxn] of node;
size,fs,h,p,c,a,q1,q2,rank,sa,fa,d:array[..maxn] of longint;
anc:array[..maxn,..] of longint;
u,e,testcase,j,t,z,i,n,m,k,x,y,len,ans,s:longint;
ch:char; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; function getf(x:longint):longint;
begin
if fs[x]<>x then fs[x]:=getf(fs[x]);
exit(fs[x]);
end; procedure update(i:longint);
begin
tree[i].s:=tree[tree[i].l].s+tree[tree[i].r].s;
end; procedure addedge(x,y:longint);
begin
inc(len);
w[len].po:=y;
w[len].next:=p[x];
p[x]:=len;
end; procedure union;
var k1,k2:longint;
begin
k1:=getf(x);
k2:=getf(y);
if k1<>k2 then
begin
if size[k1]<size[k2] then swap(x,y); //启发式合并
if size[k1]>=size[k2] then
begin
size[k1]:=size[k1]+size[k2];
fs[k2]:=k1;
end
else begin
size[k2]:=size[k2]+size[k1];
fs[k1]:=k2;
end;
end;
end; procedure sort(l,r: longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) div ];
repeat
while (a[i]<x) do inc(i);
while (x<a[j]) do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
swap(c[i],c[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; function build(l,r:longint):longint;
var q,m:longint;
begin
inc(t);
if l=r then exit(t)
else begin
q:=t;
m:=(l+r) shr ;
tree[q].l:=build(l,m);
tree[q].r:=build(m+,r);
exit(q);
end;
end; function add(last,l,r,x:longint):longint;
var q,m:longint;
begin
inc(t);
if l=r then
begin
tree[t].s:=tree[last].s+;
exit(t);
end
else begin
q:=t;
m:=(l+r) shr ;
if x<=m then
begin
tree[q].r:=tree[last].r;
last:=tree[last].l;
tree[q].l:=add(last,l,m,x);
end
else begin
tree[q].l:=tree[last].l;
last:=tree[last].r;
tree[q].r:=add(last,m+,r,x);
end;
update(q);
exit(q);
end;
end; function getans(l,r,k:longint):longint;
var m,s1:longint;
begin
if l=r then
exit(sa[l])
else begin
m:=(l+r) shr ;
s1:=tree[tree[x].l].s+tree[tree[y].l].s-tree[tree[z].l].s-tree[tree[e].l].s;
if s1>=k then
begin
x:=tree[x].l;
y:=tree[y].l;
z:=tree[z].l;
e:=tree[e].l;
exit(getans(l,m,k));
end
else begin
x:=tree[x].r;
y:=tree[y].r;
z:=tree[z].r;
e:=tree[e].r;
k:=k-s1;
exit(getans(m+,r,k));
end;
end;
end; function lca(x,y:longint):longint;
var i,p,u,v:longint;
begin
if d[x]<d[y] then swap(x,y);
if x=y then exit(x);
p:=trunc(ln(d[x])/ln());
if d[x]<>d[y] then
begin
for i:=p downto do
if d[x]- shl i>=d[y] then x:=anc[x,i];
end;
if x=y then exit(x);
u:=x;
v:=y;
for i:=p downto do
if (anc[x,i]<>anc[y,i]) and (anc[x,i]<>) then
begin
x:=anc[x,i];
y:=anc[y,i];
end; exit(fa[x]);
end; procedure maintain(x:longint);
var i,y:longint;
begin
for i:= to trunc(ln(n)/ln()) do
begin
y:=anc[x,i-];
anc[x,i]:=anc[y,i-];
end;
end; procedure dfs(x:longint);
var i,y:longint;
begin
h[x]:=add(h[fa[x]],,s,rank[x]);
maintain(x);
i:=p[x];
while i<> do
begin
y:=w[i].po;
if fa[x]<>y then
begin
d[y]:=d[x]+;
fa[y]:=x;
anc[y,]:=x;
dfs(y);
end;
i:=w[i].next;
end;
end; procedure connect(x,y:longint);
begin
fa[y]:=x; //这棵树内的父子关系会变化
anc[y,]:=x;
d[y]:=d[x]+;
dfs(y);
end; begin
readln(testcase);
readln(n,e,m);
for i:= to n do
begin
read(a[i]);
c[i]:=i;
fs[i]:=i;
size[i]:=;
end;
sort(,n);
s:=;
sa[]:=a[];
rank[c[]]:=;
for i:= to n do
begin
if a[i]<>a[i-] then
begin
inc(s);
sa[s]:=a[i];
end;
rank[c[i]]:=s;
end; for i:= to e do
begin
readln(x,y);
addedge(x,y);
addedge(y,x);
union;
end; t:=;
h[]:=build(,s);
for i:= to n do
if d[i]= then dfs(i); ans:=;
for i:= to m do
begin
read(ch);
if ch='Q' then
begin
readln(x,y,k);
x:=x xor ans;
y:=y xor ans;
k:=k xor ans;
z:=lca(x,y);
e:=h[fa[z]];
z:=h[z];
x:=h[x];
y:=h[y];
ans:=getans(,s,k);
writeln(ans);
end
else begin
readln(x,y);
x:=x xor ans;
y:=y xor ans;
addedge(x,y);
addedge(y,x);
union;
connect(x,y);
end;
end;
end.