トピックへのリンク: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 IF(1 <= 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 }