リンク:https://ac.nowcoder.com/acm/contest/3979/I
出典:牛オフネットワーク
タイトル説明
アイデア:一見すると、タイトルは私が開始できない原因、私は木の線の太さを加えた木の会長に向きを考え始めるしたいのですが、修正操作があります。
その後、私は他の人がほとんどのブロックを経由して、ブログを読んで
このコードでは、各ブロックのサイズは、SQRT(N)です。
我々合計ブロックは、次に、セグメント情報を記述するために2つの配列パラメータ:L R [i]は[I]は、i番目のブロックのエンドポイントについて説明します。
そして、ソートブロック内のデータ。
更新操作のために:私たちは、左右端点全体ブロック再度点が属する横断し、次にソートの値を更新します。
なぜ二つの別々の更新この?リフレッシュ操作が直接、更新を両方のエンドブロックをカバーするためにおそらく関係ありませんので、
(クエリが再び変更されるまで)直接更新を引き継ぐことができ、他のブロックのLRの間、我々は怠惰なラベルされたノードに移動していること、ブロック全体をカバーすることが可能です
ブロックサイズK変更操作が複雑である場合は、この方法ダウン、2 * K *ログ(K)である(ここで、両端点更新ブロック順序付け+)+ K(LRトラバース中間ブロック)
私たちは、半分の方法を使用して、裁判官によると、その答えを列挙:クエリのANSのうちは、以上のkであったかどうか
実質的に同様の更新と、残りのオペレーティング。
我々は再びそれを横断するためにあなたのブロックを周囲に終了します、更新の回答(2 * K)
、怠惰以下の答えを決定した場合にミッドレンジ、ミッドレンジ値のトラバース、プラス私たちは、全範囲を持っています
逆に、一致する回答の数を見つけるために全体の横断間隔で、LOWER_BOUND動作と実質的複雑さ(logk * K)logk、kがブロックの数です。
したがって、約クエリの複雑さ(2 * K + logk * K)*ログN; K = SQRT(N)
1の#include <ビット/ STDC ++ H> 2 の#define RINTレジスタINT 3 の#define DEB(X)CERR <<#X << "=" <<(X)<< '\ n'は、 4 使用して 名前空間STDを、 5 typedefの長い 長いLL。 6つの 使用 PII =一対< INT、INT > 。 7 CONST INT MAXN = 8E4 + 5 。 8 整数N、M、[MAXN]。 9 int型のサイズ、bNumを、LZ [MAXN]。 10 INT L [MAXN]、R [MAXN]。 11ベクトル< int型> V [MAXN]。 12 13インラインINT GET_ID(INT X){ 14 リターン X / サイズ。 15 } 16 17インラインボイド更新(int型 L、INT R、INT X){ 18 のint ID = GET_ID(L)。 19 であれば(L [ID] < L){ 20 V [ID] .clear(); 21 のために(INT ; I <= R [ID] I ++ iがL [IDを] = {) 22 [I] = 分([I]、LZ [ID])。 23 もし(I> = L && I <= r)は[I] = 分([I]、X)。 24 V [ID] .push_back([I])。 25 } 26 ソート(V [ID])(.begin、V [ID] .END())。 27 ID ++ ; 28 } 29 であれば(ID> = bNumを)リターン; 30 一方、(R [ID] <= R && ID < bNumを){ 31 LZ [ID] = 分(LZ [ID]、X)。 32 ID ++ 。 33 } 34 35 であれば(L [ID]> R || ID> = bNumを)リターン; 36 V [ID] .clear(); 37 以下のために(INT iがL [IDを] =; I <= R [ID]; I ++ ){ 38 [I] = 分([I]、LZ [ID])。 39 もし(I> = L && I <= r)は[I] = 分([I]、X)。 40 V [ID] .push_back([I])。 41 } 42 ソート(V [ID])(.begin、V [ID] .END())。 43 } 44 45インラインint型 CK(int型 L、INT R、int型K){ 46 のint ID = GET_ID(L)、RES = 0 。 47 であれば(L [ID] < {L) 48 のための(int型私は、L =。I <=分(R [ID]、R)。I ++ ){ 49 [I] = 分([I]、LZ [ID])。 50 であれば([I] <= K)RES ++ 。 51 } 52 ID ++ 。 53 } 54 であれば(ID> = bNumを)戻りRES。 55 一方、(R [ID] <= R && ID < bNumを){ 56 であれば(LZ [ID] <= K)RES + = R [ID] - [ID] + L 1 。 57の 他 RES + = UPPER_BOUND(V [ID])(.begin、V [ID] .END()、K) - V [ID])(.begin。 58 ID ++ ; 59 } 60 であれば(L [ID]> R || ID> = bNumを)戻りRES。 61 のために(intは ; I <=分(R [ID]、R)は、i ++ iがL [IDを] = {) 62 [I] = 分([I]、LZ [ID])。 63 であれば([I] <= K)RES ++ 。 64 } 65 リターンRES。 66 } 67 68インラインINTクエリ(INT L、INT R、int型K){ 69 のint L = 1、R = 1E9、ミッド。 70 一方(L <= R){ 71 ミッド= L + R >> 1 。 72 であれば(CK(L、R、MID)> = K)、R =ミッド- 1 。 73 他 L =ミッド+ 1 。 74 } 75 リターンL。 76 } 77 78 INT メイン(){ 79 のscanf(" %D%D "、&N、&M)。 80 のために(INT iが= 0、I <N; iは++)のscanf(" %dの"、+ I)。 81 サイズ= SQRT(N)、bNumを=(N - 1)/サイズ+ 1 。 82 のために(INT iは= 0 ; I <bNumを、iは++ ){ 83 LZ [I] = 0x3f3f3f3f 。 84 L [I] = I *サイズ、R [I] = I *サイズ+サイズ- 1 。 85 もし(I == bNumを- 1)R [I] = N - 1 。 86 のために(INT J = L [i]は、J <= R [i]は、J ++ )V [i]は.push_back([J])。 87 ソート(V [i]が.begin()、V [i]は.END())。 88 } 89 ながら(M-- ){ 90 のint OP、L、R、K。 91 のscanf(" %D%D%D%D "、&OP、&L&R&K)。 92 l--、r--の。 93 であれば(OP == 1 )アップデート(L、R、K)。 94 他のprintf(" %dの\ n " 、クエリ(L、R、K))。 95 } 96 }
https://blog.csdn.net/Scar_Halo/article/details/104095690(このブログからの抜粋)