E.サーシャと配列行列セグメントツリー高速電力+

E.サーシャと配列

被験者は、あなたが自分自身について考える必要があり、特に難しいことではない、私はこの方法を開始したい、いや、非常に複雑で、その後、LJは、行列の乗算を言う、そしてあなたが書く方法を知っているそれについて考えるために私を促しました。

これは、中に入るには、ツリーラインに直接行列です。

最適化に注意し、複雑さを軽減。

書式#include <CStringの> 
の#include <iostreamの> 
の#include <アルゴリズム> 
書式#include <cstdioを> 
する#include <cstdlib> 
書式#include <キュー>
 の#define INF 0x3f3f3f3f
 使用して 名前空間はstd; 
typedefの長い 長いLL。
const  int型 MOD = 1E9 + 7 構造体マット
{ 
    LLのM [ 3 ] [ 3 ]。
}、ゼロ団結。

マット演算子 * (マットB、MAT){ 
    マットANS。
    以下のためのint型私は=1 ; iは<= 2 ; I ++ ){
         ためのint型 J = 1 ; J <= 2、J ++ ){ 
            LL、X = 0 INT K = 1 ; <= K 2 ++ k個;)x + =(AM [I] [K] * BM [K] [J])%MOD。
            ans.m [I] [j]は、X%= MOD。
        } 
    } 
    戻りANS。
} 
マット演算子 + (マットB、MAT){ 
    マットANS。
    以下のためにint型 = Iを1 ; I <= 2; I ++ のためのINT J = 1 ; J <= 2、J ++ 
            ans.m [I] [J] =(AM [I] [J] + BM [I] [J])%MOD。
    戻るANSを。
} 

マットmod_pow(マットA、LL N){ 
    マットANS = 団結。
    一方、(N){
         場合(N - 1)ANS = ANS * 
        A * = 
        N >> = 1 
    } 
    戻りANS。
} 

のconst  int型 MAXN = 1E5 + 10 
マット和[MAXN* 4 ]、怠惰[MAXN * 4 ]。
; [MAXN] V LL 

無効INITを(){ 
    アム[ 1 ] [ 1 ] =午前[ 1 ] [ 2 ] =午前[ 2 ] [ 1 ] = 1、午前[ 2 ] [ 2 ] = 0 ;
    以下のためにint型 i = 0 ; iは< 3 ; iは++)unite.mを[I] [I] = 1 以下のためにint型 = Iを0 ; iは< 3 ; I ++ のためのINT J =0 ; J < 3 ; J ++)zero.m [I] [J] = 0 ; 
} 

ボイド push_up(int型のID){ 
    和[ID] =和[ID << 1 ] +和[ID << 1 | 1 ]。
} 

ボイドビルド(int型 ID、int型の L、INT R){ 
    怠惰[ID] = 団結。
    もし(L == R){ 
        和[ID] = mod_pow(V [L])。
        返します
    } 
    INT半ば=(L + R)>> 1 
    構築(ID << 1、L、MID)。
    構築(ID << 1 | 1、ミッド+ 1 、R); 
    push_up(ID)。
} 

BOOL (マットB、MAT)と同じ{
     ためint型 i = 1 ; iが= < 2 ; iは++ ){
         ためint型の J = 1 ; J <= 2、J ++ ){
             場合(AM [I] [J] != BM [I] [J])を返す 
        } 
    } 
    戻り 
} 

ボイド push_down(int型のID){
     もし(同じ(怠惰[ID]は、)団結)を返します
    和[ID << 1 ] =和[idは<< 1 ] * 怠惰[ID]。
    合計[ID << 1 | 1 ] =和[ID << 1 | 1 ] * ]怠惰[IDと、
    怠惰[ID << 1 ]怠惰[IDを<< = 1 ] * 怠惰[ID]。
    怠惰[ID << 1 | 1 ] =怠惰[ID << 1 | 1 ] * ]怠惰[IDと、
    怠惰[ID] = 団結。
} 

ボイド更新(int型 ID、INTL、のint R、int型のx、int型のY、マットヴァル){
     場合(X <= L && Y> = {R)
        怠惰[ID] =怠惰[ID] * ヴァル。
        和[ID] =和[ID] * ヴァル。
        返します
    } 
    push_down(ID)。
    INT半ば=(L + R)>> 1 もし(x <= MID)更新(ID << 1 、L、中、X、Y、ヴァル)。
    もし(Y> MID)更新(ID << 1 | 1、中間+ 1 、R、X、Y、ヴァル)。
    push_up(ID)。
} 

マットクエリ(int型 ID、INTL、のint R、int型のx、int型のY){
     場合(X <= L && Y> = r)は戻り和[ID]。
    マットANS = ゼロ。
    INT半ば=(L + R)>> 1 
    push_down(ID)。
    もし(x <= MID)ANS = ANS +クエリ(ID << 1 、L、中、X、Y)
    もし(Y> MID)ANS = ANS +クエリ(ID << 1 | 1、中間+ 1 、R、X、Y)。
    戻るANSを。
} 

int型のmain(){ 
    INIT()。
    INTのN、M。
    scanf関数(" %d個の%のD "、&​​N、&M);
    以下のためにint型 i = 1 ; iが<= N; iは++)scanf関数を(" %のLLD "、&V [I])。
    ビルド(11 、N)
    一方、(M-- ){
         int型OPT。
        LLのL、R、X。
        scanf関数(" %d個"、&OPT)。
        もし(OPTの== 1 ){ 
            scanf関数(" %LLD%LLD%LLD "、&​​L&R&X)。
            マットヴァル = mod_pow(X)。
            アップデート(11 、N、L、R、ヴァル)。
        } 
        { 
            scanf関数(" %のLLDの%のLLD "、&​​L&R)。
            マットANS =クエリ(11 、N、L、R)。
            printf(" %LLDする\ n "、ans.m [ 1 ] [ 2 ])。
        } 
    } 
    戻り 0 
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/EchoZQN/p/11511114.html