dp/单调栈
来源:互联网 发布:淘宝女装模特名字大全 编辑:程序博客网 时间:2024/06/16 05:28
题目:hdu1506
题意:一个柱形图,宽均为1.内部最大的矩形的面积。
解答1:刚开始想的是从某个区间内找小的高遍历所有区间找出最大的矩形。但是复杂度太高啦!
正确的解答:
从每一条出发,分别求出这一条左边连续比它高的和右边连续比它高的坐标。然后遍历一遍便可以求出最大值。
左右!!!可以分别从左边和右边遍历求!!!
以左边为例:
如果左边那个比它高,那么比它左边还高的一定比它还高!
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>using namespace std;const int MAXN = 100000 + 10;long long int a[MAXN],r[MAXN],l[MAXN];int main(){ long long int n; while(~scanf("%lld",&n) && n) { for(int i = 1;i <= n;i++) scanf("%lld",&a[i]); memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); l[1] = 1; r[n] = n; for(int i = 2;i <= n;i++) { int tmp = i; while(tmp > 1 && a[tmp-1] >= a[i]) tmp = l[tmp-1]; l[i] = tmp; } for(int i = n-1;i >= 1;i--) { int tmp = i; while(tmp < n && a[tmp+1] >= a[i]) tmp = r[tmp+1]; r[i] = tmp; } long long int ans = 0; for(int i = 1;i <= n;i++) { ans = max(ans,(long long int)((r[i]-l[i]+1)*a[i])); } printf("%lld\n",ans); } return 0;}
解答2:从左、从右各维护一个单调栈。
单调栈:栈里面的元素是单调的(从小到大或者从大到小)
1、如果栈里元素从小到大:可以直接找到从该位置往左,第一个比它小的元素。
2、如果栈里元素从大到小:可以直接找到从该位置往右,第一个比它大的元素。
这个题,要找到一个位置往左、往右,第一个比它小的元素(如果比它大就可以扩展)
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int MAXN = 100005;long long int a[MAXN],l[MAXN],r[MAXN];struct g{ long long int h,n;};g q1[MAXN],q2[MAXN];int main(){ int N; while(~scanf("%d",&N) && N) { for(int i = 1;i <= N;i++) scanf("%d",&a[i]); long long int ans = 0; int top = 0; q1[0].h = 0; q1[0].n = 0; q1[++top].h = a[1]; q1[top].n = 1; l[1] = 1; for(int i = 2;i <= N;i++) { if(a[i] > q1[top].h) { q1[++top].h = a[i]; q1[top].n = i; l[i] = i; } else { while(q1[top].h >= a[i] && top >= 1) top--; q1[++top].h = a[i]; q1[top].n = i; l[i] = q1[top-1].n + 1; } } top = 0; q1[0].h = 0; q1[0].n = N+1; q1[++top].h = a[N]; q1[top].n = N; r[N] = N; for(int i = N-1;i >= 1;i--) { if(a[i] > q1[top].h) { q1[++top].h = a[i]; q1[top].n = i; r[i] = i; } else { while(q1[top].h >= a[i] && top >= 1) top--; q1[++top].n = i; q1[top].h = a[i]; r[i] = q1[top-1].n - 1; } } for(int i = 1;i <= N;i++) ans = max(ans,(long long int)((r[i]-l[i]+1)*a[i])); printf("%lld\n",ans); } return 0;}
解答3:依然是单调栈。但是只扫一遍。
有以下结论:
1、如果可以直接入栈,那么它可以向左扩展的长度为1(它自己)。
2、第二个出栈的元素的右宽是前一个出栈的元素的总宽。
3、h的左宽是上一个出栈元素的总宽。
进栈的时候你只能知道它向左扩展的长度(记录下来),出栈的时候你可以算出它向右扩展的长度(出栈意味着它比当前高度要高,就说明它向右扩展不能扩展到当前元素了,那么这个向右扩展的长度是几呢?)
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>using namespace std;int main(){ int n,h; int q[100005],l[100005]; while(~scanf("%d",&n)&&n) { long long int ans = 0; memset(q,-1,sizeof(q)); memset(l,0,sizeof(l)); int top = 0; for(int i = 1;i <= n+1;i++) { if(i!=n+1) scanf("%d",&h); else h = 0;//最后把所有的元素弹出栈 if(h > q[top]) q[++top] = h,l[top] = 1;//直接进,向左扩展为1(自己) else//凡是出栈的元素的高度都比h高(向右扩展不到当前的元素) { long long int r = 0; while(h <= q[top]) { ans = max(ans,q[top]*(l[top]+r)); r += l[top--]; } q[++top] = h; l[top] = r + 1;//加上自己 } } printf("%lld\n",ans); } return 0;}
0 0
- dp/单调栈
- poj 3494 dp+单调栈
- HDU 1506-单调栈-DP
- 【DP】【单调栈】question 题解
- POJ2082 Terrible Sets [DP 单调栈]
- hdu_4362 Dragon Ball (DP+单调栈)
- POJ 2796 Feel Good -- 单调栈,DP
- [BZOJ1057]ZJOI2007棋盘制作|DP|单调栈
- poj 2796 Feel Good 单调栈/dp
- hdu 1506(dp || 单调栈)
- HDU 1506 单调栈 (dp思想)
- Fzuoj 2260 Card Game【单调栈+Dp】
- NOIP模拟dp专题 Question 单调栈
- HDU_3401 Trade 单调dp
- 单调队列优化DP
- 单调队列优化DP
- 单调队列+DP
- dp单调队列优化
- 我的内核学习笔记6:PCI驱动probe的一点认知
- android.app.RemoteServiceException: Bad notification posted from package 异常解决
- 对Socket CAN的理解(4)——【Socket CAN接收数据流程】
- 整型、浮点型在内存中的存储方式
- Pods-Hello Pal-resources.sh: No such file or directory
- dp/单调栈
- 冰冻花,被冻住的美丽
- JQury datatables 改变处理中 显示样式
- Fragment之间的跳转
- 解决ScollView嵌套ListView只显示一条的问题
- opencv中的图像亮度变换(图像增强)
- mysql中解决:Error Code: 1044. Access denied for user 'root'@'%' to database
- 欢迎使用CSDN-markdown编辑器
- Redis详细介绍