hdu 区间的价值(RMQ+扫描)
2016-05-22 21:58
447 查看
区间的价值
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 127 Accepted Submission(s): 58
Problem Description
我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。
现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。
当然,由于这个问题过于简单。
我们肯定得加强一下。
我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。
样例解释:
长度为1的最优区间为2−2 答案为6∗6
长度为2的最优区间为4−5 答案为4∗4
长度为3的最优区间为2−4 答案为2∗6
长度为4的最优区间为2−5 答案为2∗6
长度为5的最优区间为1−5 答案为1∗6
Input
多组测试数据
第一行一个数n(1≤n≤100000)。
第二行n个正整数(1≤ai≤109),下标从1开始。
由于某种不可抗力,ai的值将会是1∼109内<b
style="color:red;">随机产生</b>的一个数。(除了样例)
Output
输出共n行,第i行表示区间长度为i的区间中最大的区间价值。
Sample Input
5 1 6 2 4 4
Sample Output
36 16 12 12 6
思路:用rmq求出所有区间的最大值,然后l[i]表示i左边有几个不小于i的数,r[i]同理。
那么我们可以求出长度为r[i]+l[i]-1的一个区间最小值是i,最大值可以用rmq求出,两者相乘即可得到长度为r[i]+l[i]-1的一个解(此解不一定最优)
我们此时知道长度为n的区间解肯定是最优的(只有一种情况),那么可以用动态规划的思想。
b[i]=max(b[i+1],ans[i]);
ans[i]是已知的长度为i的一个解,那么此时我们还需要求出大于i的所有区间里长度为i的子区间的最大值
b[i+1]则是已知的长度为i+1时的最优解,既然i+1此时已经达到了最优,我们从中取i个数,也一定能取到b[i+1],也就是说,长度为i的区间的值起码会是长度为i+1的区间的值
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define N 100080 int a ,n; long long dp [20]; int l ,r ; long long ans ,b ; void make_rmq()///建立dp数组,l[i]保存i点左边有几个不小于a[i]的数,r[i]同理 { for(int i=0;i<n;i++) dp[i][0]=a[i]; for(int j=1;(1<<j)<=n;j++) { for(int i=0;i+(1<<j)-1<n;i++) { dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } for(int i=0;i<n;i++) l[i]=r[i]=1; for(int i=1;i<n;i++) { for(int j=i-1;j>=0;) { if(a[j]>=a[i]) { l[i]+=l[j]; j=j-l[j]; } else break; } } for(int i=n-1;i>=0;i--) { for(int j=i+1;j<n;) { if(a[j]>=a[i]) { r[i]+=r[j]; j+=r[j]; } else break; } } } long long get_rmq(int s,int t)///获得s-t间最大值 { if(s==t) return a[s]; int k=(int)(log(t-s+1.0)/log(2.0)); return max(dp[s][k],dp[t-(1<<k)+1][k]); } void solve() { memset(ans,0,sizeof(ans)); for(int i=0;i<n;i++)///ans[i]表示长度为i时候的最大值(不一定是最后的解) { int ll=l[i],rr=r[i]; ans[rr+ll-1]=max(ans[rr+ll-1],a[i]*get_rmq(i-ll+1,i+rr-1)); } b[n+1]=-1; for(int i=n;i>=1;i--)///比较ans[i]和i+1的最优解,得出最大的 b[i]=max(b[i+1],ans[i]); for(int i=1;i<=n;i++) printf("%lld\n",b[i]); } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++) scanf("%d",&a[i]); make_rmq(); solve(); } return 0; }
相关文章推荐
- Hama 修改log4j日志
- 数据结构实验之栈六:下一较大值(二)
- Manacher算法 , 实例 详解 . NYOJ 最长回文
- android studio 提示 “Gradle project sync failed”
- html前端代码
- LeetCode 344:Reverse String
- 主键生成策略
- 主键生成策略
- DELL R710 错误代码汇总
- nodejs和mongodb实践
- CSS高效开发实战笔记 123
- linux下date命令得到今天日期的用法
- 大数模板
- project07zabbix 监控系统
- Python进阶-函数式编程
- 设计模式---命令模式
- STL 简单 binary heap 的实现
- 第31篇 2016计划
- 利用for循环打印实心棱形和空心棱形
- 利用for循环打印实心棱形和空心棱形