[Luogu P2801]魔法のリーダー

質問の意味は、私たちはレンジを実現することができるデータ構造を維持し、どのように多くのクエリ間隔よりも大きいか、与えられた値に等しい数を変更できるようにすることです。このセグメントツリーは書かれていると言われるが、私はqwq思わなかったので、私は「使用上品な暴力」 -ブロックを。

ブロックアプローチは√Nブロックの間隔の大きさを変更し、怠惰なマークを維持し、(√Nブロックは不等式平均最小の複雑さに従って製造)、及び間隔は、遅延に直接的にブロック全体を含むように変更された場合、我々は維持することは非常に明確ですそれが直接の行に力を変更する半ブロックであれば、操作をマーク。そして暴力と異なる何に直接問い合わせてください。実際には、また、1000年までのブロックの大きさなので、バイナリ検索を注文考慮した後なので、OKと指摘しました。

時間計算量はO(q√(nlogn))です。

実際には、アイデアは、シンボルの変更は多分少しより多くの水は、私は、レコード10,20,60,80,90最終ACを提出しなければならないだけのように、データの多くすることができ、非常にシンプルですが、比較的形而上学この事を阻止します。デバッグ時間は一時間以上のqwqについてです。

#include <cstdioを> 
する#include <cmath> 
の#include <CStringの> 
する#include <アルゴリズム> 
の#include <キュー> 
の#include <iostreamの> 
する#include <ベクトル>
 の#define N 1000010
 使用して 名前空間STD。
int型ブロック[N]、サイズ、怠惰[N]、[N]、N、Q。
ベクター < INT > B [ 10001 ]。
ボイドリセット(INT X)
{ 
    B [X] .clear(); 
    以下のためにint型 I =(X - 1)*サイズ+ 1 ; iは=分(X・サイズを<、n)は、I ++)B [X] .push_back( [I]); // 代替の順序付けられたシーケンスを取るプロ配列を直接注文することができない
    並べ替え(B [X] .begin()、B [X] .END()); 
} 
無効追加(int型 L、int型の R&LT、INT K)を
{ 
    IF(ブロック[L] == ブロック[R&LT])//間隔ブロック直接暴力動作を有する
    { 
        ためint型 = L Iを、I <= R&LT; I ++ )A [I] + = K; 
        RESET(ブロック[L]); 
        を返す; 
    } 
    ためのint型 + Iが=ブロック[L]を1。 ;私は=ブロック[R&LTを< - 1。 ; I ++)は怠惰[I] + = kは、右遅延マーキング操作に//ブロック全体
     のためのint型 = I L、Iは<=ブロック[L] *サイズは、I ++は)A [I] + =K; 
    リセット(ブロック[L])。
    int型 - ; I>(ブロック[R] I = rは1 [I] + =; i--)*サイズ)K。
    リセット(ブロック[R])。
    返します
} 
int型の照会(int型 L、int型の R、int型K)
{ 
    int型 RET = 0 もし(ブロック[L] == ブロック[R])
    { 
        ためint型 I = 1と、iが<= R; iは++)場合([I] +遅延[ブロック[L]]> = K)RET ++ リターンRET; 
    } 
    のためのINTI =ブロック[L] + 1 ; iは=ブロック[R] < - 1 ; iは++ 
    { 
        RET + = B [i]を.END() - B [i]は.begin() - (LOWER_BOUND(B [I]を.begin()、B [i]は.END()、K -怠惰[I]) - 、B [i]は.begin()); //二分查找多少个数比(K -怠惰[i])と大。
    } 
    のためにint型 I = 1と、iは<; iは++ =ブロック[L] *サイズ)なら([I] +遅延[ブロック[I]]> = K)RETを++ 以下のためにint型 I = R; I>(ブロック[R] - 1)*サイズ; i--)場合([I] +遅延[ブロック[I]]> = K)RET ++ リターンRET; 
} 
int型のmain()
{ 
    scanf関数("%D%D "&N、& Q); 
    サイズ =(INT )SQRT(N)
     のためにint型 i = 1 ; iが<= N; iが++ 
    { 
        scanf関数(" %のD 、および[I])。
        ブロック[I] =(I - 1)/サイズ+ 1 
        。; B [ブロック[I]一back([I])
    } 
    ためのint型 i = 1 ; iが=ブロックを<n]はiが++ ソート) (B [i]を.begin()、B [i]は.END());
     一方(q-- 
    { 
        int型、L、R、K CHARオペアンプ; 
        cinを >> オペアンプ。
        scanf関数(" %D%D%D "、&​​L&R&K)。
        もし(OP == ' A ')のprintf(" %d個の\ n " 、クエリ(L、R、K))。
        (L、R、k)を加えます。
    } 
    戻り 0 
}

 

おすすめ

転載: www.cnblogs.com/lijilai-oi/p/10991545.html