來自《挑戰程序設計競賽》
1.單調棧的應用
1.POJ2559
1.題目原文
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 19669 | Accepted: 6359 |
Description
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
Input
Output
Sample Input
7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0
Sample Output
8 4000
Hint
Source
2.解題思路
3.AC代碼
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<string>
#include<set>
#include<vector>
#include<cmath>
#include<bitset>
#include<stack>
#include<sstream>
#include<deque>
using namespace std;
#define INF 0x7fffffff
const int maxn=100005;
typedef long long ll;
int n;
int h[maxn];
int L[maxn],R[maxn];
void solve()
{
//計算L
stack<int> s;
for(int i=0;i<n;i++){
while(!s.empty()&&h[s.top()]>=h[i]){
s.pop();
}
L[i]=(s.empty())?0:(s.top()+1);
s.push(i);
}
while(!s.empty()){
s.pop();
}
//計算R
for(int i=n-1;i>=0;i--){
while(!s.empty()&&h[s.top()]>=h[i]){
s.pop();
}
R[i]=(s.empty())?n:s.top();
s.push(i);
}
ll res=0;
for(int i=0;i<n;i++){
res=max(res,(ll)h[i]*(R[i]-L[i]));
}
printf("%lld\n",res);
}
int main()
{
while(scanf("%d",&n)!=EOF&&n){
for(int i=0;i<n;i++){
scanf("%d",&h[i]);
}
solve();
}
return 0;
}
2.POJ3250
3.POJ2796
2.雙端隊列的應用
1.滑動最小值
1.題目原文
給定一個長度爲n的數組a[0],a[1],a[2],……a[n-1].求數組b[i]=min{a[i],a[i+1],……a[i+k-1]}(i=0,1,2,n-k)。2.解題思路
3.代碼
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<string>
#include<set>
#include<vector>
#include<cmath>
#include<bitset>
#include<stack>
#include<sstream>
#include<deque>
using namespace std;
const int maxn=1e6+5;
int n,k;
int a[maxn],b[maxn];
void solve()
{
deque<int> deq;
//雙端隊列是遞增的
for(int i=0;i<n;i++){
//在雙端隊列末尾加入i
while(!deq.empty()&&a[deq.back()]>=a[i]){
deq.pop_back();
}
deq.push_back(i);
if(i-k+1>=0){
b[i-k+1]=a[deq.front()];
if(deq.front()==i-k+1){
//從雙端隊列的隊頭刪除元素
deq.pop_front();
}
}
}
for(int i=0;i<n-k;i++){
cout<<b[i]<<" ";
}
cout<<b[n-k]<<endl;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
solve();
return 0;
}