小さな店(D11配列GCD)を給油5028 bzoj Z(フェンウィックツリーセグメントツリー+)

問題の意味

2つの一連の動作を考えると、一つはGCDインターバル期間を求め、他の値はインターバル期間を追加することです。(イタリアの前後にボトルシャッフリング内部の範囲内にあるべきであるということ、それはなぜ間隔の最大公約数にようである参照してください、そして最後に、あなたは、顧客への油のボトルをしたい、その後知ることができるもの定理シュウペイによります

問題の解決策

公知の技術によれば、減少GCD(X、Y)= GCD (X、Y-X)、 次いで、容易に入手可能な 3つの数のGCDのための(X、Y、Z) = GCD(X、Y-X、ZY)。

ヒープの性質の任意の整数倍が確立されていることを証明するために数学的帰納法を使用して簡単に

差があるように、上記の式ではないでしょうか?

したがって、我々は[L]および[L + 1、rはこの差間隔をGCDができるだけを知って変更する場合、2つの修飾一点に間隔を変更する差を使用することができます。

差動アレイのために我々はフェンウィックツリーを使用することができるセグメントツリーのメンテナンス間隔は、メンテナンスの単一点の値について、GCD構築することができます。

、Lの場合、クエリは、== rは直接値に[L]、又は特クエリが0を返すセグメントツリーの決意を与えることに留意されたいフォークABSを取ります

R == N R + 1を変更しない場合は変更します

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、

const  int型 MAXN = 100005 ;
INTのN、M、根、NUM。
int型[MAXN] B、[MAXN]。
int型の LS [MAXN << 1 ]、RS [MAXN << 1 ]、GCD [MAXN << 1 ]。
int型CX [MAXN]。

テンプレート < クラス T>インラインボイドリード(T&X){ 
    X = 0チャー CH = GETCHAR()。
    しばらく(!isdigit(CH))CH = getchar関数();
    一方、(isdigit(CH)){X =(X << 1)+(X << 3)+(CH ^ 48)、CH = GETCHAR();} 
} 

int型 get_gcd(INT A、INT B){
     戻り B?A:get_gcd(B、%のB)。
} 

ボイド更新(INT RT){ 
    GCD [RT] = get_gcd(GCD [LS [RT]、GCD [RS [RT])。
} 

ボイドビルド(INT&RT、int型の L、INT R){
     もし RT = ++(RT!)NUM。
    もし(L == R){GCD [RT] [L]を=。リターン;}
     int型ミッド=(L + R)>> 1
    ビルド(LS [RT]、L、MID)。
    ビルド(RS [RT]、ミッド + 1 、R)。
    アップデート(RT)。
} 

ボイド追加(int型のx、int型のval){ ため(; X <= Nであり、X + = X&-x)CX [X] + = ヴァル;} 

int型の和(INT X){
     int型 RET = 0 (; X; X - = X& - X)
     RET + = CX [X]。
    リターンRET; 
} 

int型の照会(INT RT、INT L、のint R、int型の L、INT R){
     もし(L <= 1 && R <= R)戻りGCD [RT]。
    INT半ば=(L + R)>> 1 もし(R <= MID)戻りクエリ(LS [RT]、L、中、L、R)。
    もし(MID <L)戻りクエリ(RS [RT]、ミッド+ 1 、R、L、R)。
    戻り get_gcd(クエリ(LS [RT]、L、中、L、R)、クエリ(RS [RT]、ミッド+ 1 、R、L、R)); 
} 

ボイドは、(変更INT RT、INT L、のint R、int型 POSを、INT ヴァル){
     場合(L == R){ 
        GCD [RT] + = ヴァルと、
        リターン; 
    } 
    INT半ば=(L + R)>> 1 もし(POS <= MID)(LS [RT]、L、中間、POS、ヴァル)を修正します。
    そうでなければ(RS [RT]、ミッド+修正1 、R、POS、ヴァル)を、
    アップデート(RT)。
} 

int型のmain(){ 
    (n)を読み出す;(m)を読み出します。
    以下のためにint型 i = 1 ; iが<= N; iは++ )読み出す([I])。
    int型 [I- = - [I] i--; I I = n)を1 ]、([i]は、i)を加えます。
    ビルド(ルート、1 、N)
    int型 I = 1 ; I <= M Iは++ ){
         int型OP、L、R。
        (OP)を読み出す;(l)を読み出す;(r)を読み取ります。
        場合(L> R)スワップ(L、R)。
        もし(OPの== 1 ){
             場合(L == R)のprintf(" %d個の\ n " 、和(L))。
            のprintf(" %d個の\ n "、ABS(get_gcd(和(L)、クエリ(ルート、1、N、L + 1 、R))))。
        } 
        {
             int型V、
            (v)を読みます。
            追加(L、v)は、追加(R + 1、 - V)。
            変更(ルート、1 、N、L、V)。
            もし(R <N)を変更(ルート、1、N、R + 1、 - V)。
        } 
    } 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/sto324/p/11240530.html