Luogu_P4556雨尾[解説]ツリー差セグメントツリーの合併

質問表面:https://www.luogu.com.cn/problem/P4556

(x、y)のZプラス1でパスに。

ツリーには違いがあることができます。

xおよびyがインクリメントされます。LCAはマイナス1、マイナス1つのLCAは父です。

しかし、多くの異なる種があるためです。

各点は、ツリーラインを維持するために必要。

合併のどの種類の最大を求めているとき。

最後に、統計的な答えは、DFS。

シンプルなアイデアは、メインコードは長いです。 

コードは以下の通りであります:

#pragma -gcc-最適化( "O2、Ofast、インライン、アンロール-全てループ、-ffast-数学")
 の#pragma -gcc-目標( "AVX、SSE2、SSE3、SSE4、POPCNT")
の#include <ビット/ 。STDC ++ H>
 使用して 名前空間STDを、
 CONST  INT MAXN = 100010 ;
 int型TT、N、M、
 構造体ノード{
     int型NXT、へ;
     の#define NXT(X)E [X] .nxt
     の#define(X)E [xに] .TO 
} E [MAXN << 1 ];
 int型のヘッド[MAXN]、TOT、DEP [MAXN]、[MAXN] [F 21 ]、RT [MAXN]、NUM、CNT、X [MAXN]、Y [MAXN ]、Z [MAXN]、valが[MAXN]は、[MAXN] ANS; 
インラインボイド(追加のint X、int型のY){ 
    (に TOT ++)= yと; 
    NXT(TOT) =ヘッド[X];頭部[X] = TOTを、
} 
キュー < INT > Q。
インライン長い{read()は
     長い X = 0、F = 1チャー C = GETCHAR()。
    一方、(C> ' 9 ' || C < ' 0 '){ もし、(C == ' - ')、F * = - 1 ; C = GETCHAR();}
     一方、(C> =' 0 ' && C <= ' 9 ')、X = X * 10 + C- ' 0 '、C = GETCHAR()。
    リターンのx *のF; 
} 
インラインボイドBFS(){ 
    q.push(1); DEPは、[ 1 ] = 1 一方、(q.size()){
         int型のx = q.front(); q.pop()。
        以下のためにint型 I =ヘッド[X]; I; I = NXT(I)){
             int型 =への(I)
            もし(DEP [に対して])続行
            【に】DEP = DEP [X] + 1 
            F [に対する] 0 ] =のX。
            INTの J = 1 J ++; J <= TT 
                F [へ] [J] = F [F [へ] [J- 1 ]] [J- 1 ]。
            (へ)q.push。
        } 
    } 
} 
インラインINT LCA(int型のx、int型Y){
     場合(DEP [X]> DEP [Y])スワップ(X、Y)
    以下のためにint型私はTTを=; I> = 0 ; i-- の場合(DEP [F [Y] [I]]> = DEP [X])Y = F [Y] [I]。
    もし(x == y)は戻りX。
    以下のためにint型 = TTをIを、I> = 0 ; i-- であれば(!F [x]は[I] = F [Y] [i])と、X = F [X] [i]は、Y = Y [F ][私];
    戻り [X] [F 0 ]。
} 
構造体ツリー{
     int型LC、RC、DT、TG。
} T [MAXN * 80 ]。
ボイド挿入(int型 P、int型の L、INT R、INT VL、INT D){
     場合(1- == {R)
        T [P] .DT+ = D。
        T [P] .tg = T [P] .DT?L:0 返します
    } 
    INT半ば=(L + R)>> 1 もし(VL <= MID){
          場合(!T [P]を得た。LC)T [P]を得た。LC = ++ NUM。
         (T [P]を得た。LC、L、中間、VL、D)を挿入します。
     } {
          場合(!T [P] .RC)T [P] .RC = ++ NUM。
         インサート(T [P] .RC、中間 + 1 、R、VL、D)。
     } 
     T [P] .DT = MAX(T [T [P]を得た。LC] .DT、T [T [P] .RC] .DT)。
     T [P] .tg = T [T [P]を得た。LC] .DT> = T [T [P] .RC] .DT?T [T [P]を得た。LC] .tg:T [T [P] .RC] .tg。
} 
INTマージ(INT P、整数 qは、整数 L、INT R){
     場合(!P)リターンQ。
    もし(!Q)リターンのp;
    もし(L == R){ 
        T [P] .DT + = T [Q] .DT。
        T [P] .tg = T [P] .DT?L:0 リターンのp; 
    } 
    INT半ば=(L + R)>> 1 
    T [P]を得た。LC = マージ(T [P]を得た。LC、T [Q]を得た。LC、L、MID)。
    T [P] .RC =マージ(T [P] .RC、T [Q] .RC、ミッド+1 、R)。
    T [P] .DT = MAX(T [T [P]を得た。LC] .DT、T [T [P] .RC] .DT)。
    T [P] .tg = T [T [P]を得た。LC] .DT> = T [T [P] .RC] .DT?T [T [P]を得た。LC] .tg:T [T [P] .RC] .tg。
    リターンのp; 
} 
ボイド DFS(int型X){
     ためint型 I =ヘッド[X]; I; I = NXT(I)){
         int型 =の(I)に、
        もし([に対する] DEP <= [X] DEP)続けます
        DFS(へ)。
        室温[X] =([X]、RT、[TO] RTマージ1 CNT)。
    } 
    ANS [X] = T [RT [X]のTgを。
} 
INT )(主
{
    N = read()は、M = read()は、
    TT =(INT)(ログ(N)/ログ(2))+ 1 以下のためにint型私= 1 ; iがN <; Iは++ ){
         int型 X、Y; X =読み取る(); Yは。= 読み取ります(); 
        (x、y)を追加し、(x、y)を加えます。
    } 
    BFS()。
    以下のためにint型 i = 1 ; iが<= N; iは++)RTを[I] = ++ NUM。
    以下のためにint型 I = 1 ; I <= M; iは++ ){ 
        X [i]が読み取り=(); Y [i]を読み出す=(); Z [I] = 読み取ります(); 
        ヴァル[I] = Z [i]は、
    } 
    ソート(ヴァル + 1、ヴァル+ 1 + M)。
    CNT =ユニーク(ヴァル+ 1、ヴァル+ 1 + M)-val- 1 以下のためにint型 I = 1 ; I <= M; iは++ ){
         int型、X = X [i]は、Y = Y [i]は、
        INT Z = LOWER_BOUND(ヴァル+ 1、ヴァル+ 1 + CNT、Z [i])と- ヴァル。
        INT LC = LCA(X、Y)
        インサート(RT [X]、1、CNT、Z、1 )。
        (RT [Y]、インサート1、CNT、Z、1); 
        (RT [LC]、インサート1、CNT、Z、 - 1 )。
        もし([LC]は[F 0 ])を挿入する(RT [F [LC] [ 0 ]、1、CNT、Z、 - 1 )。
    } 
    DFS(1 )。
    以下のためにint型私= 1 iが++; iが<= N)のprintf(" %d個の\ n " 、ヴァル[ANS [I])を、
    リターン 0 ; 
}

 

おすすめ

転載: www.cnblogs.com/ChrisKKK/p/11544029.html