POJ 2796 字首陣列或者單調棧

2021-08-03 22:43:48 字數 1598 閱讀 1261

poj 2796

題意:

給出乙個陣列,求出某乙個數字和其所在的區間和的乘積最大值,輸出最大值和左右區間的邊界。其區間的定義是比這個數字大的區間。

思路:

正常的思路是列舉求出每乙個數字的區間,然後算出乘積。問題是如何減少複雜度。

這裡可以用陣列的字首和。左右區間的話也可以加速比較。

比如左區間:a[i] <= a[l[i]-1],那麼l[i] = l[l[i]-1];

#include 

#include

using

namespace

std;

const

int maxn = 100005;

int n;

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

int main()

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

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

}long

long ans = -1;

int l,r;

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

}printf("%i64d\n%d %d\n",ans,l,r);

return

0;}

定義乙個棧st,其實也可以用陣列模擬棧。

1. 定義乙個結構體s[maxn],s[i].m 表示下表, s[i].l左邊界,s[i].r表示右邊界,s[i].x 表示原來的值。

2. 我們維護乙個s[i].x遞增的棧,從1到n開始遍歷,當當前s[i].x大於st.top().x的時候s[i].l = i;

3. 當小於的時候很明顯st.top().r = i -1,s[i].l = st.top().l,然後棧頂出棧重複這個過程。

4. 最後如果st不為空,則裡面所有的結構題s[i].r = n;

5. 最後依次列舉找出最大值就行。

#include 

#include

#include

using

namespace

std;

const

int maxn = 100005;

struct node

s[maxn];

int n;

stack

st;long

long sum[maxn];

int main()

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

st.push(s[i]);

}while(!st.empty())

long

long ans = -1;

int l,r;

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

}printf("%i64d\n%d %d\n",ans,l,r);

return

0;}

單調棧的進一步理解,poj2796

對於單調棧,則是乙個單調的棧,為什麼可以把複雜度減小為0 n 主要是在求以乙個數為最小的區間和的時候,可以在資料處理時構建乙個單調棧,已知乙個單調的棧,再往下面壓入乙個數時,如果不滿足單調性,則表明暫棧頂元素最小的區間已經結束了,那麼就pop出來,如果棧頂第二個元素也不滿足單調性,那麼也壓出,但是由...

poj2796 動態規劃思想 回溯 單調棧第一題

一般來說,有動態規劃思想的都是動態規劃水題。當然,前提是你完全理解了動態規劃思想 給定你一些數,要求你找乙個區間,要求這個區間內的數的和乘以這個區間內最小的數,要求這個積最大。簡直蒙蔽,後來發現說單調棧也能寫,但是不會單調棧。看懂題解了,就是先沒個數左邊的數 這是確定的,並且要從左往右求,這樣可以利...

poj2796 區間和乘最小值之最大值

題目 給出正整數的陣列,讓你求出此陣列某乙個區間的和乘以區間內的最小值的最大值。例 3 1 6 4 5 2 在第3到第5個數的區間內,和為15最小值為4乘積60最大。wa include include include include using namespace std struct node ...