區間最小值 區間元素和最大(dp懸線法 )

2022-06-08 18:21:10 字數 2102 閱讀 7524

傳送門

懸線法

題目大意:

對於乙個長度為n的數列,找出乙個子區間,

使子區間內的最小值與子區間元素和的乘積最大,

要求在滿足舒適值最大的情況下最小化長度,

最小化長度的情況下最小化左端點序號。

本題中我們可以考慮列舉最小值,將每個位置的數a[i]當作最小值,並考慮從i向左右擴充套件,找到滿足

的盡可能向左右擴充套件的區間 。這樣本題就被轉化成了懸線法模型這個題最主要的還是要求出l[i]和r[i]

l[i]和r[i]代表的是如果i是最小值的話向左和向右延申的最大下標

例如

3:如果讓3做最小值的話,下標最左是1,最右也是1

1:如果讓1做最小值的話,下標最左可以達到1,最右可以達到6

,,,,,

#include #include

#include

#include

using

namespace

std;

const

int n = 100010

;int

n, a[n], l[n], r[n];

long

long

sum[n];

long

long

ans;

intansl, ansr;

bool fir = 1

;int

main()

for (int i = 1; i <= n; i++)

while (a[l[i] - 1] >= a[i]) l[i] = l[l[i] - 1

];

for (int i = n; i >= 1; i--)

while (a[r[i] + 1] >= a[i]) r[i] = r[r[i] + 1

];

for (int i = 1; i <= n; i++)

printf(

"%lld\n%d %d\n

", ans, ansl, ansr);

} return0;

}

#include #include

#include

#include

using

namespace

std;

//懸線法

/*對於乙個長度為n的數列,找出乙個子區間,

使子區間內的最小值與子區間元素和的乘積最大,

要求在滿足舒適值最大的情況下最小化長度,

最小化長度的情況下最小化左端點序號。

*/typedef

long

long

ll;const

int maxn = 100010

;int

l[maxn],r[maxn],a[maxn];

ll sum[maxn];

ll ans;

bool fir = 1

;int

ansl,ansr;

intmain()

for(int i=1;i<=n;i++)

for(int i=n;i>=1;i--)

for(int i=1;i<=n;i++)

}printf(

"%lld\n

",ans);

printf(

"%d %d\n

",ansl,ansr);}}

區間最大最小值 ST表

這是一道st表經典題 靜態區間最大值 請注意最大資料時限只有0.8s,資料強度不低,請務必保證你的每次查詢複雜度為 o 1 o 1 若使用更高時間複雜度演算法不保證能通過。如果您認為您的 時間複雜度正確但是 tle,可以嘗試使用快速讀入 inline int read while isdigit c...

ST表 (求區間最大 最小值)

st表的功能很簡單 它是解決rmq問題 區間最值問題 的一種強有力的工具 它可以做到o nlogn 預處理,o 1 是查詢最值 像線段樹是o logn 的查詢 st表是利用的是倍增的思想 拿最大值來說 我們用st i j 表示,從i位置開始的2 j個數中的最大值,例如st i 1 表示的是i位置和i...

線段樹求區間最大值和最小值(指標)

鏈結 include include using namespace std define max a,b a b?a b define min a,b al a s r b if a 1 b 不是葉子結點線段 return s void update linetree s,int a,int b ...