2019HDUマルチ学校第K番目の最短距離 - バイナリツリーの会長&&

問題の意味

$ N $、$ Q $に与えられる数は$のL、R、P、k個の$のいずれかに排他的又は回答の各々を、尋ねる依頼する時間があり、実際の値(すなわち力である)です。小さな$ K $ $の各クエリ、出力$ [のL、R] $ | PA [I] | $。

分析

ツリーの議長は、通常Kの大きいセクションを見つけるために使用され、実際には、その実用的効果は、一定の範囲内の値の数をカウントすることです。そのため、

各お問い合わせは、$ R_L \ simのR_r $ツリーラインに可能な答えを$ xに$に対する答えの半分は$ [PX、P + X] $か$ kの$を検索します。

値上に構築された会長の木、$ 10 ^ 6 $至るまでのデータのこの問題、無ディスクリート(私はしません離散の力によって言葉

多くの場合、一部のカードを感じ、32倍、55倍のスペースは、(ああ、なぜ)上で64倍に変更し、TLEあります

#include <ビット/ STDC ++ H.>
 使用して 名前空間STD; 

のconst  int型 MAXN 1E5 + = 100 ;
 INT N-、M;
 // INT A [MAXN];
 // INT RT [MAXN]、LC [<< MAXN 5] RC [MAXN << 5]、SUM [MAXN << 5];   // RT:ルートノードLC / RCの異なるバージョン:息子は左右息子(パブリック)合計:及び(パブリック)は
int型 RT [MAXN]、LCを【MAXN * 64 ]、RC [MAXN * 64 ]、SUM [MAXN * 64 ];
 int型 node_cnt;     // ノードの総数、pnt_disc:Bに対応するデジタル値
のint =範囲1000000 ;   // データの範囲は、セグメントツリーはの大きさである

ボイドビルド(int型&last_node、int型の L、int型R)
{ 
    last_node = ++ node_cnt。
    和[last_node] = 0 ;
    もし(L == R)の   リターン;
    INT半ば=(L + R)>> 1 
    (LC [last_node]、L、中間)を構築します。
    (RC [last_node]、中間ビルド + 1 、R)。
} 


int型(変更INT pre_rt、INT V、INTを L、INT R)
{ 
    int型 new_rt = ++ node_cntと、
    LC [new_rt] =LC [pre_rt]。
    RC [new_rt] = RC [pre_rt]。
    和[new_rt] =和[pre_rt] + 1 

    INT半ば=(L + R)>> 1 もし(L == R)   戻りnew_rt。
    もし(MID> = V)LC [new_rt] = 修正(LC [new_rt]、V、L、MID)。
    他の   RC [new_rt] =変更(RC [new_rt]、V、中間+ 1 、R)。
    リターンnew_rt。
} 

// 查询[QL、QR]中不同元素个数
INTクエリ(INT RT1、INT RT2、INT QL、INT QR、INT L、INT R)
{ 
    // のprintf( "RT1:%D RT2:%のDK:%のDL:%のDRた:%d"、RT1、RT2、K、L、R)。
    もし(QL <= 1 && R <= QR)   戻り和[RT2] - 和[RT1]。

    INT半ば=(L + R)>> 1 int型 ANS = 0 ;
    もし(QL <= MID)ANS + = クエリ(LC [RT1]、LC [RT2]、QL、QR、L、MID)。
    もし(QR> MID)ANS + =クエリ(RC [RT1]、RC [RT2]、QL、QR、中間+ 1 、R)。
    戻るANSを。
} 

ボイドprint_debug()
{ 
    のprintf(" node_cnt:%Dを\ n " 、node_cnt)。
    int型 I = 0 ; I <= node_cnt iが++ 
        のprintf(" :%D RC:%dの合計%Dを\ n%d個のLC " 、I、LC [i]は、RC [i]は、和[I ]); 
} 

int型のmain()
{ 
    int型のT。
    scanf関数(" %のD "、&T)。
    一方、(T-- 
    { 
        scanf関数(" %d個の%のD "、&​​N、&M)。

        node_cnt = 0 ; 
        (RT [ビルド0 ]、1 、範囲)。
        以下のためのINT I = 1 ; I <= N; I ++ 
        { 
            int型TMP; 
            scanfの(" %のD "、&TMP); 
            RT [I] =修正(RT [I- 1 ]、TMP、1。 レンジ);   // 唯一のバージョンに基づいて改変
        } 

        INT ANS = 0 ;
         のためint型 I = 0 ; iがm <; I ++は
        { 
            int型のLは、R、P、K、
            scanfの(" %D%D%D%D "、&​​Lは、R&、&P、およびK); 
            L^ = ANS; R ^ =のANS。
            P ^ =のANS; K ^ =のANS。
            場合(L> R)スワップ(L、R)。

            INTは L = 0、R =レンジ。      //
             一方(L <= R)
            { 
                int型 M = Lの+(RL)/ 2 もし(クエリ(RT 1- [ 1 ]、RT [R]、MAX(1、PM)、分(P + M、範囲)、1、範囲)> = K)
                { 
                    ANS = M。
                    R = M- 1 
                }
                他の   L = M + 1 ; 
            } 
            のprintf(" %d個の\ n " 、ANS)。
        } 
    } 
} 
[クリップボードにコピー]、[ファイルに保存]

 

 

参考リンク:

1.  https://blog.csdn.net/birdmanqin/article/details/97964662

2.  http://morecoder.com/article/1254619.html

おすすめ

転載: www.cnblogs.com/lfri/p/11289552.html