[BZOJ1803] Spoj1487 Query on a tree III

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1803

题目大意

查询子树第k大

题解

dfs序+主席树

const
    maxn=100005;
var
    seg:array[0..20*maxn,1..3]of longint;
    pos,x:array[0..maxn,1..2]of longint;
    w:array[0..3*maxn,1..2]of longint;
    y,root:array[0..maxn]of longint;
    i,j,k:longint;
    n,m,len,slen,a,b:longint;
procedure sort(l,r:longint);
var i,j,a,b:longint;
begin
    i:=l; j:=r; a:=x[(i+j)div 2,1]; 
    repeat
        while x[i,1]<a do inc(i);
        while x[j,1]>a do dec(j);
        if not(i>j) then
            begin
                b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
                b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
                inc(i); dec(j);
            end;
    until i>j;
    if l<j then sort(l,j);
    if i<r then sort(i,r);
end;

procedure init(a,b:longint);
begin
    w[len,1]:=b;
    if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;
    w[a,1]:=len; inc(len);
end;

procedure build(pre,now,l,r,val:longint);
var mid:longint;
begin
    seg[now,3]:=seg[pre,3]+1;
    if l=r then exit;
    mid:=(l+r)>>1; seg[now,1]:=seg[pre,1]; seg[now,2]:=seg[pre,2];
    if val<=mid 
    then begin inc(slen); seg[now,1]:=slen; build(seg[pre,1],slen,l,mid,val) end
    else begin inc(slen); seg[now,2]:=slen; build(seg[pre,2],slen,mid+1,r,val); end;
end;

function query(pre,now,l,r,k:longint):longint;
var mid,tt:longint;
begin
    if l=r then exit(l);
    mid:=(l+r)>>1; tt:=seg[seg[now,1],3]-seg[seg[pre,1],3];
    if tt>=k
    then exit(query(seg[pre,1],seg[now,1],l,mid,k))
    else exit(query(seg[pre,2],seg[now,2],mid+1,r,k-tt));
end;

procedure dfs(a,fa:longint);
var tt:longint;
begin
    tt:=w[a,2]; inc(len); pos[a,1]:=len; inc(slen); root[len]:=slen; build(root[len-1],root[len],1,n,y[a]);
    while tt<>0 do
        begin
            if w[tt,1]<>fa then dfs(w[tt,1],a);
            tt:=w[tt,2];
        end;
    pos[a,2]:=len;
end;

begin
    readln(n); len:=n+1;
    for i:=1 to n do
        begin
            read(x[i,1]);
            x[i,2]:=i;
        end;    
    sort(1,n); {x[i,1]}
    for i:=1 to n do
        y[x[i,2]]:=i;
    for i:=1 to n-1 do
        begin
            readln(a,b);
            init(a,b); init(b,a);
        end;
    len:=0; slen:=0; dfs(1,0);
    readln(m);
    for i:=1 to m do
        begin   
            readln(a,b);
            writeln(x[query(root[pos[a,1]-1],root[pos[a,2]],1,n,b),2]);
        end;
end.

你可能感兴趣的:([BZOJ1803] Spoj1487 Query on a tree III)