羅区P3157 / BZOJ3295 [CQOI2011動的逆の順序

ブロックは良いアルゴリズムです

特に、私にとってこれは木のカバーツリーをだますません。

番号を削除すると、それが逆に貢献見つけることは困難である、それは数よりも小さい場合、その背後にあるその前の数+よりも大きい番号の数を、そのブロックを使用することは非常に簡単です:

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、11 << 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 ; 
}
コードの表示

それから私は、木のカバーの木を学習する必要はありません

おすすめ

転載: www.cnblogs.com/sunshine-chen/p/11258807.html