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 ...