[HDU-6621] K番目の最短距離の議長ツリーツリーライン2019上学校4

トピックへのリンク:http://acm.hdu.edu.cn/showproblem.php?pid=6621

質問の意味:| P-AI |配列に、繰り返しrは最初のkの小さなセクションを尋ねたL、R、K、P、L〜を尋ねたいくら
1 <= P、aiを<1E6 、1 <= K <= 169 、R - L + 1> = K、1 <= N、M <= 10 ^ 5

溶液:バイナリ回答+社長ツリー
回答rの絶対値-half、その後社長ツリー検索[PR、P + R]間隔の数の数、等しい以上をk rが増加するよりも減少Rと記録回答k番目する場合
AケースのR存在に正確になるまで、RはKを満たすが、この時点で存在していないRの答えが半分より小さくRなりである
現在のノードLのツリー維持総数少数の〜r値の範囲の社長もっと

公式の説明

セグメントツリーを使用して、我々はO内[L、R]のpよりも小さい値の数(ログ(N))を見つけることができます。

だから、二分探索法を用いることで、我々はOで答え(ログ(N)^ 2)時間を見つけることができます。

合計時間の複雑さは、O(Nログ(N)+ Qログ(N)^ 2)です。

 

ACコード:

1の#include <ビット/ STDC ++ H.>
 2  使用して 名前空間STD;
 3のtypedef ロング ロングLL;
 4  int型 CONST MAXN = 1E5 + 100、maxn2 = 1E6 + 10 ;
 5  int型 M、N-、Q、A [MAXN]、TOT、Froot [MAXN]、C [maxn2 * 30 ]、LSON [maxn2 * 30 ]、rson [maxn2 * 30 ]; // 40倍オープンスペース会長ツリーnは、典型的には十分
。6  
。7  INTの更新(INT根、int型の POS、int型ヴァル){ // 前にツリーの新しいツリー、ルートの新しい価値を加えた後
。8      int型NEWROOT = TOT ++、TMP = NEWROOT;
 9      C [NEWROOT] = C [ルート] +ヴァル; // 新しいツリーのノード値=ツリーの前回値+新たに追加された
10      のint L = 1、R&LT = 1E6;
 11      ながら(L < R&LT){
 12である         INT MID =(L + R&LT)>> 1 ;
 13で         IF {(POS <= MID)// 参照変更された値は、サブツリーた片である
14              LSON [NEWROOT] TOT = ++; rson [ NEWROOT] =のrson [ルート]; // 左サブツリーであれば、元の木の右の部分木の値が使用できる
15              =ルート; NEWROOT LSON = [NEWROOT] LSON [ルート];
 16              R&LT = MID;
 17          }
 18          {
 19。              rson [NEWROOT] = TOT ++; LSON [NEWROOTは] = ; LSON [ルート]
 20は              、ルート=の; [NEWROOT] NEWROOT = rson rson [ルート];
 21である              L = MID + 。1 ;
 22である         }
 23は          = C [NEWROOT] C [ルート] + ヴァル;
 24      }
 25      リターン TMP; // 新しいツリーのルートノード
26は }
 27  INTクエリ(INT L、INT R&LT、INT K、INT LR、int型のRR){
 28      // 現時点のL、R木の数字は、RR、第LRた
 29      //間隔照会するには、ポイント制御区間[L、R]現在[1、K] 
30      IF(K> = R&LT)リターン C [RR] - C [LR];
 31である     INT MID =(L + R&LT)>> 。1、ANS = 0 ;
 32      IF1 <= MID ANS + =)クエリ(L、MID、K、LSON [LR]、LSON [RR]);
 33は、     IF(K> MID)ANS + =クエリ(MID + 1 、R&LT 、[LR]、rson [RR] rson K);
 34は、     戻りANSを;
 35  }
 36  INT query_node(INT LR、INT RR、INT P、INT K){ // 保守セグメントツリー番号
37 [      INT= L 0は、R = 1E6は、MID、ANS、アルは、Ar、GG; // 回答の絶対値の半分の半径| P-AI | 
38は     、一方(L <= R&LT){
 39          MID =(L + R&LT)>> 。1 ;        
 40          アル= MID-P、P +のAr = MID; // らを見- AR数のセクション番号、<K場合、半径が増加する、<=半径をk個の場合に可能であるかもしれません(現在割り当てられた番号が存在しない可能性があるため)それは小さくする必要がありますが、答えは、小さなができません少し大きすぎるなければなりません。
41は、         IF(アル<= 1)GG =クエリ(1、1E6は、Ar、Froot [LR]、Froot [RR]); // ら<0、0〜ARは数どれだけ参照する場合は
42である         他の GG =クエリ(1、1E6は、Ar、Froot [LR]、Froot [RR]) -クエリ(1、1E6、のAl- 1。、Froot [LR]、Froot [RR]);
 43は、         IF(GG> = K){
 44の              ANS =ミッド; R =半ば1 45          }
 46          他の L =ミッド+ 1 47      }
 48の     リターンANS。
49  }
 50  int型のビルド(int型 L、int型 R){ // 初始建树
51      のintルート= TOT ++ 52個の      C [ルート] = 0 ;
53      であれば(!L = R){
 54          INT半ば=(L + R)>> 1 55          LSON [ルート] =(L、ミッド)を構築します。
56          rson [ルート] =ビルド(MID + 1 、R)。
57      }
 58      リターンルート。
59  }
 60インラインINT get_num(){
 61      チャーCH。
62      ブールフラグ= 63      のint NUM = 0 64      CH = GETCHAR()。
65      一方(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ')フラグ= ; CH = GETCHAR();}
 66      ながら、(CH> = ' 0 ' && CH <= ' 9 '){NUM =(NUM << 3)+(NUM << 1)+ CH- ' 0 ' ; CH = GETCHAR();}
 67      であれば(フラグ)リターン - 1 *のNUM。
68      リターンNUM;
69  }
 70  INT メイン(){
 71          のint T、ANS。
72          のscanf(" %dの"、&T)。
73          しばらく(T-- ){
 74          のscanf(" %D%D "、&​​N、&Q)。
75          TOT = 0、ANS = 0 76          のためにint型 i = 1 ; iが++; iが<= N ){
 77              [I] = get_num()。
78          }
 79          
80          froot [ 0 ] =ビルド(1 、1E6)。
81          のためにint型 i = 1 ; iが<= N iが++ ){
 82              froot [I] =アップデート(froot [I- 1 ]、[I]1 );
83          }
 84          ながら(q-- ){
 85              のint L、R、P、K。
86              L = get_num()^ ANS、R = get_num()^ ANS、P = get_num()^ ANS、K = get_num()^ ANS。
87の              ANS = query_node(1- 1 、R、P、K)。
88              のprintf(" %d個の\ n " 、ANS)。
89          }    
 90          }
 91          
92      戻り 0 ;
93 }

 

おすすめ

転載: www.cnblogs.com/conver/p/11286918.html