现在的位置: 首页 > 综合 > 正文

bzoj2588

2018年01月15日 ⁄ 综合 ⁄ 共 3191字 ⁄ 字号 评论关闭

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit:
128 MB
Submit: 194  Solved: 62
[Submit][Status][Discuss]

Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

 
M行,表示每个询问的答案。

Sample Input

8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

HINT

HINT:

N,M<=100000

暴力自重。。。

随着主席树的出现……这类问题以沦为经典问题……

每个节点维护他到根路径上的权值线段树,然后减出来就好了……

虽然代码略长,但是很好写……

Count on a tree II我不会,求拯救

program bzoj2588;
var
	u,v,tot,all,ans,n,m,i,j,k:longint;
    h,ent,root,new,a:array [0..100001] of longint;
    next,point:array [0..200001] of longint;
    fa:array [0..20,0..100001] of longint;
    left,right,sum:array [0..3000001] of longint;

procedure swap (var a,b:longint);
begin
    if a=b then exit;
    a:=a xor b;
    b:=a xor b;
    a:=a xor b;
end;

procedure connect (u,v:longint);
begin
    inc(tot);
    point[tot]:=v;
    next[tot]:=root[u];
    root[u]:=tot;
end;

procedure insert (x,now,last:longint);
var
    l,r,mid:longint;
begin
    l:=1;
    r:=all;
    repeat
        sum[now]:=sum[last]+1;
        if l=r then break;
        mid:=(l+r) div 2;
        if x<=mid then
            begin
                inc(tot);
                left[now]:=tot;
                right[now]:=right[last];
                now:=tot;
                last:=left[last];
                r:=mid;
            end
                    else
            begin
                left[now]:=left[last];
                inc(tot);
                right[now]:=tot;
                now:=tot;
                last:=right[last];
                l:=mid+1;
            end;
    until false;
end;

function find (x,x1,x2,x3,x4:longint):longint;
var
    l,r,mid:longint;
begin
    l:=1;
    r:=all;
    while l<>r do
        begin
            mid:=(l+r) div 2;
            if sum[left[x1]]+sum[left[x2]]-sum[left[x3]]-sum[left[x4]]>=x then
                begin
                    r:=mid;
                    x1:=left[x1];
                    x2:=left[x2];
                    x3:=left[x3];
                    x4:=left[x4];
                end
                                                                                                        else
                begin
                    x:=x-(sum[left[x1]]+sum[left[x2]]-sum[left[x3]]-sum[left[x4]]);
                    l:=mid+1;
                    x1:=right[x1];
                    x2:=right[x2];
                    x3:=right[x3];
                    x4:=right[x4];
                end;
        end;
    exit(l);
end;

procedure build (s,e,now:longint);
var
    mid:longint;
begin
    if s=e then exit;
    mid:=(s+e) div 2;
    inc(tot);
    left[now]:=tot;
    build(s,mid,tot);
    inc(tot);
    right[now]:=tot;
    build(mid+1,e,tot);
end;

procedure qsort (s,e:longint);
var
    i,j,k:longint;
begin
    if s>=e then exit;
    i:=s;
    j:=e;
    k:=new[(s+e) div 2];
    while i<=j do
        begin
            while new[i]<k do inc(i);
            while new[j]>k do dec(j);
            if i>j then break;
            swap(new[i],new[j]);
            inc(i);
            dec(j);
        end;
    qsort(s,j);
    qsort(i,e);
end;

function convert (x:longint):longint;
var
    s,e,mid:longint;
begin
    s:=1;
    e:=all;
    while s<>e do
        begin
            mid:=(s+e) div 2;
            if new[mid]<x then s:=mid+1
                                else e:=mid;
        end;
    exit(s);
end;

procedure dfs (now,high:longint);
var
    i:longint;
begin
    h[now]:=high;
    i:=0;
    while fa[i,fa[i,now]]<>0 do
        begin
            fa[i+1,now]:=fa[i,fa[i,now]];
            inc(i);
        end;
    inc(tot);
    ent[now]:=tot;
    insert(a[now],tot,ent[fa[0,now]]);
    i:=root[now];
    while i<>0 do
        begin
            if point[i]<>fa[0,now] then
                begin
                    fa[0,point[i]]:=now;
                    dfs(point[i],high+1);
                end;
            i:=next[i];
        end;
end;

function lca (a,b:longint):longint;
var 
    i:longint;
begin
    if h[a]>h[b] then swap(a,b);
    while h[a]<>h[b] do
        b:=fa[trunc(ln(h[b]-h[a])/ln(2)),b];
    if a=b then exit(a);
    i:=20;
    repeat
        if fa[0,a]=fa[0,b] then exit(fa[0,a]);
        while fa[i,a]=fa[i,b] do dec(i);
        a:=fa[i,a];
        b:=fa[i,b];
    until false;
end;

begin
    read(n,m);
    for i:=1 to n do
        read(a[i]);
    for i:=1 to n do
        new[i]:=a[i];
    for i:=1 to n-1 do
        begin
            read(u,v);
            connect(u,v);
            connect(v,u);
        end;
    qsort(1,n);
    i:=1;
    while i<=n do
        begin
            inc(all);
            new[all]:=new[i];
            while (i<=n)and(new[i]=new[all]) do inc(i);
        end;
    for i:=1 to n do
        a[i]:=convert(a[i]);
    tot:=0;
    build(1,all,0);
    dfs(1,1);
    for i:=1 to m do
        begin
            read(u,v,k);
            u:=u xor ans;
            j:=lca(u,v);
            ans:=new[find(k,ent[u],ent[v],ent[j],ent[fa[0,j]])];
            writeln(ans);
        end;
end.
【上篇】
【下篇】

抱歉!评论已关闭.