セグメントツリーの最適化DP(次期の選択)

数日試験前に、今私はそれをチューニングを考えます。

問題の意味

格子から選択される、選択された最小量の要件が、各選択されたグリッドの範囲が制限されている:ABS(JK)<= W [i]は[J] W + [I-1]別の値であるW [K]

暴力:O(N×m個×m個の* T)

最適化は、選択されるグリッド線、グリッドの行が処理を覆うようにする範囲について、および範囲から選択することができ、所望の急速なグリッドで、その結果、行を選択し、最小量の細胞。

最小のメンテナンスと、各ラインのセグメントツリー、次線分ツリー排出を入れて、再修正

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#define半ば((L + R)>> 1)
 の#define N 105
 の#define M 5005
 の#define INF 0x7f7f7f
 INT A [N] [M]、DP [N] [M]、ミネソタ州[M * 4 ]、FL [M * 4 ]、L [N] [M]、R [N] [M]。
ボイド更新(int型の)
{ミネソタ[S] =分(ミネソタ州[S << 1 ]、ミネソタ州[S << 1 | 1 ])。}
 ボイドプッシュダウン(INT S)
{ 
    場合(FL [S] == INF)のリターン; 
    ミネソタ州[S << 1=分([I << 1 ]に[I])。
    [Sにおける << 1 ] =分(IN [S << 1 ]、[I]において)。
    [から << 1 | 1 ] =分([I << 1 | 1 ]に[I])。
    で[ << 1 | 1 ] =分([S <<で1 | 1 ]に[I])。
    で[S] = INF。
} 
ボイドビルド(もし「sは、あなたがしていると、あなたがR)
{ 
    で[S] = INF。
    OW(L == R){[I] = INF。  戻り}; 
    (Sビルド << 1(<< Sビルド;、L、MID)を1 | 1、MID + 。1 ;、R&LT)
    更新(S); 
} 
ボイド変更(INT S、int型の L、INT R&LT、int型の L 、INT R&LT、int型V)
{ 
    IF(L <= R&LT && L <= R&LT){ 
        ミネソタ[S] =分(ミネソタ州[S]、V); //を更新することを忘れないようにしてください!
        FL [S] = 分(FL [S]、V);
         返す; 
    } 
    プッシュダウン(S)は、// クエリを変更し、下流側がマークされている
    場合(L <= MID)変更(S << 1 、L、中間、L、R、V)。
    場合(R>中間)が変更(S << 1 | 1、中間+ 1 、R、L、Rを、V)。
    更新(S); 
} 
int型の照会(INT S、INT L、のint R、int型の L、INT R)
{ 
    場合(L <= 1 && R <= R)戻りミネソタ[S]。
    プッシュダウン(S); 
    int型 ANS = infファイル。
    もし(L <= MID)ANS =分(ANS、クエリ(S << 1 、L、中間、L、R));
    もし(R>中旬)ANS =分(ANS、クエリ(S << 1 | 1、ミッド+ 1 、R、L、R));
    戻るANSを。
} 
int型のmain()
{ 
    freopenは(" elect.in "" R " 、STDIN)。
    freopenは(" elect.out "" W " 、STDOUT)。
    INT T、N、M。
    scanf関数(" %D%D%D "、&​​T、&N、&M)。
    一方、(T-- ){
         int型 ANS = 0x7f7f7f 以下のためにint型 i = 1 ; iが<= N。についてINT J = 1。 ; J <= M; J ++ 
          scanfの(" %のD "、&​​A [I] [J]);
         のためのINT I = 1 ; I <= N; I ++ のためのINT J = 。1 ; J <= M; J ++ ){
              int型X; 
             scanfの(" %のD "、およびX); 
             L [I] [J] = MAX(1、JX); // 各ラインの各点に対して得られます最大距離値の最もセグメントツリーメンテナンス間隔カバーに 
             R&LTを[I] [J] =分(M、J + X)。
         } 
        ビルド(11 、M);
        以下のためにint型 I = 1 ; I <= M; iは++ 
         DP [ 1 ] [I] = [ 1 ] [i]は、修正(11、M、L [ 1 ] [i]は、R [ 1 ] [I]、DP [ 1 ] [I])。
        以下のためにint型 I = 2 ; iが<= N; iは++ ){
              ためのint型 J = 1 ; J <= Mであり、j ++ 
               DP [I] [J] =クエリ(11、M、L [i]は[ j]は、R [I] [J])+ [I]、[J]; ビルド11、M); // 行は、セグメントツリーに対応!再構築に使用後の行
             のためのINT J = 1。 ; J <= M; J ++ 
             変更(11 、M、L [I] [J]は、R [I]、[J]、DP [I] [J ]); 
        } 
        のためのINT I = 1 ; I <= M、Iが++)ANS = 分(ANS、DP [N-] [I]); 
        のprintf(" %Dの\のN- " 、ANS); 
    } 
} 
/ * 
1 
3. 5 
。9 8 7 3 5 
8 9 2 8 6 
。1. 9 7 8 6 

0 0 1 1 2
1 0 2 1 1 
0 2 1 0 2 
* /

 

おすすめ

転載: www.cnblogs.com/mowanying/p/11222832.html
おすすめ