ブロックは良いアルゴリズムです
特に、私にとってこれは木のカバーツリーをだますません。
番号を削除すると、それが逆に貢献見つけることは困難である、それは数よりも小さい場合、その背後にあるその前の数+よりも大きい番号の数を、そのブロックを使用することは非常に簡単です:
1.寄与計算ブロックの前面およびブロックの数、その暴力におけるブロックの後半;
2.それを削除し、バックの削除が前方に移動した後の列の元の数、ブロック数をマーキング。
複雑さを書く$ O(M用の\ SQRT {N} LOGN)非常に危険な$、であり、私たちは\その後複雑性は$ O(Mまで低下し、ブロックサイズは$ \ SQRT {nlogn} $としたことを見出しましたSQRT {nlogn})$、しばしばカードを容易に交流することができませんでした。
#include <cstdioを> する#include <cmath> の#include <CStringの> する#include <アルゴリズム> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 N = 100050 ; チャーはrB [ 1 << 21 ]、* S * T、WB [ 1 << 21 ]。 int型 WP = - 1 ; インラインチャー GC(){ 戻り S == T &&(T =(S = rBの)+関数fread(RB、1、1 << 21、STDIN)、S == T)EOF:* S ++ ;} インラインボイドフラッシュ(){関数fwrite(WB、1、WP + 1、STDOUT); WP = - 1 ;} インラインボイド PC(チャー C){ 場合(WP + 1 ==(1 << 21))のフラッシュ(); WB [ ++ WP] = C;} インラインint型RD(){ チャー C = GC()。 一方、(C < 48 || C> 57)C = GC()。 INT X = C&15 。 用(;> = C、C = GC()48 && C <= 57、X =(X <<; C = GC())3)+(X << 1)+(C&15 )。 リターンのx; } 短い BUF [ 25 ]。 インラインボイド重量(LLのX){ 短い L = - 1 。 一方、(X> 9 ){ BUF [ ++ L] = X%10 。 X / = 10 。 } PC(X | 48 )。 一方、(L> = 0)PC(BUF [1 - ] | 48 )。 PC(' \ nを' ); } // 快读/快写 int型[N]、B [ 100 ] [ 1300 ]、C [N]、T [N]、N、X、SZ [ 100 ]、K、CNT、POS [N]。 LL ANS = 0 。 ブールD [N]。 ボイド MS(int型 L、INT R){ // 归并排序求初始逆序对数 であれば(L == R)のリターン; INT M = L + R >> 1、I = L、J = M + 1、K = L。 MS(L、M); MS(M + 1 、R)。 一方、(I <= M && J <= R)であれば(C [i]が<= C [J])T [K ++] = Cを[I ++ ;] 他{ ANS + = M-I + 1; T [K ++] =のC [J ++ ]。 } 一方(iは<= M)T [K ++] = Cを[I ++ ]。 一方、(j <= R)T [K ++] =のC [J ++ ;] 用(i = L、I <= R; iは++)C [I] =のT [i]は、 } インラインボイドビルド(){ int型私は、jは、 K = SQRT(N *ログ(N)/ログ(2))。もし K =(K!)1 ; CNT = N / K。 // 1つの*ログ(1)= 0、碰上毒瘤数据(这题没有)会RE 用(i = 1 ; iは= CNTを<; iは++ ){ ため(J = 1 ; J <= K; J ++)B [I]は[j]は= [(I- 1)* K + J]。 ソート(B [i]は + 1、B [I] + K + 1 ); SZ [I] = K; } IF(N-%K){ CNT ++ ; のための(I = 1 ; I <= N%K。 I)はB [CNT] [I]は= A [(CNT- ++ 1)* K + I]、 並べ替え(B [CNT] +を1、B [CNT] + N-%のK個の+ 1 ); SZ [CNT] = N-%K ; } } インラインボイド inupper(INT P、INT X){ // ブロック番号で半分より大きな値 のint L = 1。、R&LT SZ = [P]、M、S = SZ [P] + 1 ; 一方、(L <= R&LT){ M = L + R&LT >> 1 ; IF(B [P] [M]> X){S = M; R&LT = M- 1 ;} 他の L = Mの+ 1 ; } ANS - = SZ [P] -s + 1 ; } インラインボイド inlower(int型 P、INT X){ // のブロックを半分より小さい値数 int型 L = 1、R&LT SZ = [P]、M、S = 0 ; 一方、(L <= R&LT){ M = L + R&LT >> 1 。 もし(B [P] [M] <X){S = M、L = M + 1 ;} そうでなければ、R = M- 1 。 } ANS - =のS。 } インラインint型の検索(INT P、INT X){ // 暴力搜 INT L = 1、R = SZ [P]、M。 一方、(L < R){ M = L + R >> 1 。 もし(B [P] [M]> = X)R = M。 他 L = M + 1 。 } 戻りL。 } インラインボイドワーク(){ int型の P =(X + K- 1)/ K、I、T = 見つける(P、[X])。 用(i = 1 ; iはpは<; iは++ )inupper(I、[X])。 以下のための(I = P + 1 ; iは= CNT <; iは++ )inlower(I、[X])。 以下のための(I =(P- 1)* K + 1 ; iは<X、iは++)場合(D [i]は&& [I]!> ans-- [X]) 。 以下のための(I = X + 1、iが<= P * K && I <= N; iは++)場合 ans--(D [i]は&& [I] <[X]!)。 D [X] = 1。 // 删除标记 ため(I = tの、I <SZ [P]; iは++)B [P] [I] = bの[P] [I + 1 ]。 //删除一个数后后面的数要前移 SZ [P] - ; // このブロック低減素子内 } int型のmain(){ int型M、I; N- = RD(); RD = M() - 1 ; // これで、最終的な出力は、次いで、応答しないこと処理されていない ため(I = 1 POS [I] = RD()] = I;;; I <= N-Iが++) // 削除するタイトルがそう位置に注目することは、数ある )(ビルド; のmemcpy( C、A、はsizeof (C)); MS(1 、N-); 質量(ANS); 一方(M-- ){ X = POS [RD()]; ワーク(); 質量(ANS); } フラッシュ( ); 戻り 0 ; }
それから私は、木のカバーの木を学習する必要はありません