JZOJ 4604 树【NOIP2016模拟7.11】

来源:互联网 发布:单片机通信协议哪种好 编辑:程序博客网 时间:2024/05/17 12:56

题目描述

这里写图片描述

输入格式

这里写图片描述

输出格式

这里写图片描述

样例输入

5 5
1 2
1 3
2 4
2 5
Q 2
C 2
Q 2
Q 5
Q 3

样例输出

1
2
2
1

数据范围

这里写图片描述

题解

解法一:树链剖分,暴力维护即可,表示我不会,比赛时我打了解法二(出题人提供的正解)。
解法二:离线处理,并查集。

倒着过来做,先将所有需要标记的点全部标记,然后遍历一次,求出每个点最近的那个打了标记的祖先,并向其连一条边,连接到其集合内。

当一个点的标记消失时,将此点向它的父亲连一条边,表示加入他父亲的集合。
每次查询时,查找自己那个集合内的祖先,此祖先就是最近的那个打了标记的祖先,也就是答案。(此算法的正确性就不证明了,证明很简单,很显然,请读者自行思考)

Code(Pascal)

var    ch,cc:char;    n,m,q,i,j,k,l,o,p,oo:longint;    cz:array[0..101000,1..2] of longint;    bb,da,fa,ans,en:array[0..101000] of longint;    bj:array[0..201000,1..2] of longint;procedure cqyadd(x,y:longint);    begin        inc(en[x]);        inc(en[y]);        inc(oo);        bj[oo,1]:=x;        bj[oo,2]:=y;        inc(oo);        bj[oo,1]:=y;        bj[oo,2]:=x;    end;procedure bh;    var        i:longint;    begin        bb[1]:=1;        fa[1]:=1;        da[1]:=1;        randomize;        for i:=1 to n do        en[i]:=en[i-1]+en[i];        for i:=1 to m div 2 do        begin            k:=random(m div 2)+m div 2;            bj[0]:=bj[i];            bj[i]:=bj[k];            bj[k]:=bj[0];        end;    end;procedure qsort(l,r:longint);    var        i,j,m:longint;    begin        i:=l;        j:=r;        m:=bj[(l+r) div 2,1];        repeat            while bj[i,1]<m do inc(i);            while bj[j,1]>m do dec(j);            if i<=j then            begin                bj[0]:=bj[i];                bj[i]:=bj[j];                bj[j]:=bj[0];                inc(i);                dec(j);            end;        until i>j;        if l<j then qsort(l,j);        if i<r then qsort(i,r);    end;procedure dg(o:longint);    var        i:longint;    begin        for i:=en[o-1]+1 to en[o] do        if da[bj[i,2]]=0 then        begin            da[bj[i,2]]:=o;            if fa[bj[i,2]]=0 then fa[bj[i,2]]:=fa[o];            dg(bj[i,2]);        end;    end;function lookfor(o:longint):longint;    begin        if fa[o]=o then exit(o);        fa[o]:=lookfor(fa[o]);        exit(fa[o]);    end;begin    readln(n,q);    for i:=1 to n-1 do    begin        readln(o,p);        cqyadd(o,p);    end;    m:=2*n-2;    bh;    qsort(1,m);    for i:=1 to q do    begin        read(ch);        read(cc);        readln(cz[i,2]);        if ch='C' then        begin            cz[i,1]:=1;            inc(bb[cz[i,2]]);            fa[cz[i,2]]:=cz[i,2];        end        else cz[i,1]:=2;    end;    dg(1);    for i:=q downto 1 do    begin        if cz[i,1]=2 then ans[i]:=lookfor(cz[i,2])        else        begin            dec(bb[cz[i,2]]);            if bb[cz[i,2]]=0 then            fa[cz[i,2]]:=fa[da[cz[i,2]]];        end;    end;    for i:=1 to q do    if cz[i,1]=2 then writeln(ans[i]);end.
3 0
原创粉丝点击