您的位置:首页 > 其它

bzoj3551 3545

2015-06-20 17:01 288 查看
我直接来讲在线好了

这是一个很巧妙的方法,把边作为一个点

做一遍最小生成树,当加如一条边时,我们把这条边两点x,y的并查集的根i,j的父亲都设为这条边代表的点k,由k向i,j连边

这样我们就构建出一棵树,这棵树的叶子都是原来节点

且每棵子树都是在子树根所代表的边的限制下的最小连通块

这样我们就可以通过dfs序(只用对叶子标号)+主席树来维护k大了并通过倍增找到限制

这两题都是一副卡pascal过不了的样子……QAQ

另外网上的一些标称(bzoj3551)似乎没有考虑一个点没有边可走,但询问k=1的情况,可以加数据cha

type node=record
po,next:longint;
end;
way=record
x,y,z:longint;
end;
point=record
l,r,s:longint;
end;

var e:array[0..400010] of node;
w:array[0..500010] of way;
v:array[0..400010] of boolean;
anc:array[0..200010,0..20] of longint;
d,l,r,p,fa,c,a,b,h:array[0..200010] of longint;
tree:array[0..200010*20] of point;
num,j,s,size,i,len,t,n,m,q,x,y,ans,k:longint;

function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;

function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;

function getf(x:longint):longint;
begin
if fa[x]<>x then fa[x]:=getf(fa[x]);
exit(fa[x]);
end;

procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end;

procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr 1];
repeat
while a[i]<x do inc(i);
while x<a[j] do dec(j);
if i<=j then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;

procedure qsort(l,r:longint);
var i,j,x:longint;
y:way;
begin
i:=l;
j:=r;
x:=w[(l+r) shr 1].z;
repeat
while w[i].z<x do inc(i);
while x<w[j].z do dec(j);
if i<=j then
begin
y:=w[i]; w[i]:=w[j]; w[j]:=y;
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;

procedure dfs(x:longint);
var i,y:longint;
begin
v[x]:=true;
if x<=n then
begin
inc(num);
b[num]:=x;
l[x]:=num;
r[x]:=num;
exit;
end;
i:=p[x];
l[x]:=n;
r[x]:=0;
while i<>0 do
begin
y:=e[i].po;
anc[y,0]:=x;
dfs(y);
l[x]:=min(l[x],l[y]);
r[x]:=max(r[x],r[y]);
i:=e[i].next;
end;
end;

function find(x,y:longint):longint;
var i:longint;
begin
for i:=size downto 0 do
if a[anc[x,i]]<=y then x:=anc[x,i];
exit(x);
end;

function build(l,r:longint):longint;
var m,q:longint;
begin
inc(t);
q:=t;
if l<>r then
begin
m:=(l+r) shr 1;
tree[q].l:=build(l,m);
tree[q].r:=build(m+1,r);
end;
exit(q);
end;

function add(l,r,last,x:longint):longint;
var m,q:longint;
begin
inc(t);
q:=t;
if l=r then tree[q].s:=tree[last].s+1
else begin
m:=(l+r) shr 1;
if x<=m then
begin
tree[q].r:=tree[last].r;
tree[q].l:=add(l,m,tree[last].l,x);
end
else begin
tree[q].l:=tree[last].l;
tree[q].r:=add(m+1,r,tree[last].r,x);
end;
tree[q].s:=tree[tree[q].l].s+tree[tree[q].r].s;
end;
exit(q);
end;

function ask(l,r,x,y,k:longint):longint;
var m,s:longint;
begin
if l=r then exit(c[l])
else begin
m:=(l+r) shr 1;
s:=tree[tree[y].r].s-tree[tree[x].r].s;
if s>=k then exit(ask(m+1,r,tree[x].r,tree[y].r,k))
else exit(ask(l,m,tree[x].l,tree[y].l,k-s));
end;
end;

procedure ins(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end;

begin
readln(n,m,q);
for i:=1 to n do
begin
read(d[i]);
a[i]:=d[i];
b[i]:=i;
end;
sort(1,n);
s:=1;
d[b[1]]:=1;
c[1]:=a[1];
for i:=2 to n do
begin
if a[i]<>a[i-1] then
begin
inc(s);
c[s]:=a[i];
end;
d[b[i]]:=s;
end;
for i:=1 to 2*n do
fa[i]:=i;
for i:=1 to m do
readln(w[i].x,w[i].y,w[i].z);

qsort(1,m);
t:=n;
fillchar(a,sizeof(a),0);
for i:=1 to m do
begin
x:=getf(w[i].x);
y:=getf(w[i].y);
if x<>y then
begin
inc(t);
fa[x]:=t;
fa[y]:=t;
a[t]:=w[i].z;
ins(t,x);
ins(t,y);
if t=2*n-1 then break;
end;
end;

a[0]:=2147483647;
len:=t;
for i:=1 to len do
if not v[i] then dfs(getf(i));
size:=trunc(ln(len)/ln(2)+0.1);
for j:=1 to size do
for i:=1 to len do
begin
x:=anc[i,j-1];
anc[i,j]:=anc[x,j-1];
end;
t:=0;
h[0]:=build(1,s);
for i:=1 to num do
h[i]:=add(1,s,h[i-1],d[b[i]]);
ans:=-1;
for i:=1 to q do
begin
readln(x,y,k);
{ if ans<>-1 then
begin
x:=x xor ans;
y:=y xor ans;
k:=k xor ans;
end;        }
x:=find(x,y);
if x<=n then
begin
if k=1 then ans:=c[d[x]]
else ans:=-1;
end
else if tree[h[r[x]]].s-tree[h[l[x]-1]].s<k then ans:=-1
else ans:=ask(1,s,h[l[x]-1],h[r[x]],k);
writeln(ans);
end;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: