HDU学校第1005(hdu6638)雪Smilelセグメントツリー/最大範囲を超えると

質問の意味:

マトリックスが与えられると、行列はポイント数を有し、各点は、最大ブロックの箱入り生体重中点のいくつかのその点を見つけるために、正または負の重み付け値を有しています。

ソリューション:

離散的な水平および垂直座標は、この問題は簡単に最大とマトリックス上のサブ行列を求める問題に変換されます。

共通のn×n個の行列のサブ行列、および$(N ^ 3)Oの$、上下端DP列挙として解釈される最大

しかし、この質問は、スパース行列、n個の* nの行列のみO(n)のポイントは、$ O(N ^ 2logn)$ソリューションが必要です。

下端点に最大セグメントツリーメンテナンス間隔と各列挙で、上下端を列挙することで、下端値上の全ての点に対して権利がツリーラインに更新される正解、各更新LOGN

点の数はO(N)であるので、その結果、列挙エンドポイント更新セグメントツリーの各合計時間複雑さ$ OとO(N)、(N ^ 2logn)$まで

 

間隔と最大で以下の情報を保存のセグメントツリーのノード:合計(和)、maxsum(最大サブセグメント)、Lmaxと(及び最大のプレフィックス)、(最大及びサフィックス)のRmaxが

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
typedefの長い 長いLL。
typedefのペア < int型、LL> P;
const  int型 M = 2E3 + 5 constの LL MOD = 998244353 ;
constの LL LINF = 0x3f3f3f3f3f3f3f3f #define LS(RT << 1)
 の#define RS(RT << 1 | 1)
LLのGCD(LL、LL b)は{ 戻り B?GCD(B、%のB)。}
 構造体ノード{
     int型のL、R。
    LLの合計値、lsmx、rsmx、MX。
} TR [M* 4 ]; 
LL A [M]; 
LLプリ、ANS; // 右端と先頭からサブセグメントの最大を事前検索スペース前、ANS現在の最大
空隙押し上げ(INT RT)
{ 
    TR [RT] .SUM = TR [LS] + .SUM TR [RS] .SUM; 
    TR [RT] .lsmx = MAX(TR [LS] + .SUM TR [RS] .lsmx、TR [LS] .lsmx); 
    TR [RT]。 rsmx = MAX(TR [RS] + .SUM TR [LS] .rsmx、TR [RS] .rsmx); 
    TR [RT] .MX = MAX(MAX(TR [LS] .MX、TR [RS] .MX )、TR [LS] + .rsmx TR [RS] .lsmx); 
} 
ボイドビルド(INT RT、int型の L、INT R&LT)
{ 
    TR [RT] .L = L、TR [RT] .R =R;
    もし(L == R)
    { 
        TR [RT] .SUM + = [L]。
        TR [RT] .lsmx + = [L]。
        TR [RT] .rsmx + = [L]。
        TR [RT] .MX + = [L]。
        返します
    } 
    INT半ば=(L + R)>> 1 
    (LS、L、ミッド)を構築。
    構築(RS、ミッド + 1 、R); 
    突き上げ(RT)。
} 
ボイド更新(int型 RT、int型の L、int型の R、int型のPOS、LLのV)
{
    もし(L == R)
    { 
        TR [RT] .SUM + = V。
        TR [RT] .lsmx + = V。
        TR [RT] .rsmx + = V。
        TR [RT] .MX + = V。
        返します
    } 
    INT半ば=(L + R)>> 1 もし(POS <= MID)
        更新(LS、L、中間、POS、V)。
    他の
        更新(RS、ミッド + 1 、R、POS、V); 
    突き上げ(RT)。
} 
のクエリ(int型 RT、int型 QL、int型QR)
{ 
    場合(QL <= TR [RT] .L && TR [RT] .R <= QR)
    { 
        ANS = MAX(ANS、TR [RT] .MX)。
        ANS = MAX(ANS、プリ+のTR [RT] .lsmx)。
        予備 = MAX(プリ+ TR、[RT] .SUM TR [RT] .rsmx)。
        返します
    } 
    INT半ば=(TR [RT] .L + TR [RT] .R)>> 1 もし(QL <= MID)
    { 
        クエリ(LS、QL、QR)。
    } 
    であれば(QR> MID)
    { 
        クエリ(RS、QL、QR)。
    } 

} 
int型のn;
int型Q; 
LL X [M]、Y [M]、ヴァル[M]。
LLのXID [M]、YID [M]。
int型xsz、YSZ。
ベクター <P> VEの[M]。
INT のmain()
{ 
    int型_。
    scanf関数(" %のD "、&_)。
    一方、(_-- 
    { 
        scanf関数(" %のD "、&N)
        以下のためにint型 i = 1 ; iが<= N; iは++ 
        { 
            scanf関数(" %LLD%LLD%LLD "、およびX [i]は、&​​Y [i]は、&ヴァル[I])。= X [i]は、
            YID [I] = Y [I]を、
        } 
        ソート(YID + 1、YID + 1個の + N)。
        ソート(XID + 1、XID + 1個の + N)。
        xsz =ユニーク(XID + 1、XID + 1個の + N) - (XID + 1 )。
        YSZ =ユニーク(YID + 1、YID + 1個の + N) - (YID + 1 )。
        以下のためにint型 I = 1 ; I <= YSZ; iは++ 
        {
            VEの[I] .clear(); 
        } 
        のためにint型 i = 1 ; iがn = <; iは++ 
        { 
            int型XI、YI。
            XI = LOWER_BOUND(XID + 1、XID + 1 + xsz、X [I]) - XID。
            YI = LOWER_BOUND(YID + 1、YID + 1 + YSZ、Y [I]) - YID。
            VEの[イル] .push_back(make_pair(XI、ヴァル[I]))。
        } 
        ANS = 0 以下のためのint型私は= 1 ; I <= YSZ;私は++)//下边界
        { 
            memsetの(TR、0はsizeof TR)。
            int型 J = I; J> = 1 ; j--)// 上边界
            {
                 ための(自動TMP:VEの[J])
                { 
                    更新(11 、xsz、tmp.first、tmp.second)。
                } 
                ANS = MAX(ANS、TR [ 1 ] .MX)。
            } 
        } 
        のprintf(" %LLDを\ n " 、ANS)。
    } 
}

 

おすすめ

転載: www.cnblogs.com/isakovsky/p/11323176.html