poj 2452(RMQ+二分查找)
2016-04-03 20:33
337 查看
题目链接:
http://poj.org/problem?id=2452
题意:在区间[1,n]上找到满足 a[i]<a[k]<a[j] (i<=k<=j) 的最大子区间 (j-i)如不存在输出 -1.
思路:枚举i,找到 i右边第一个不大于(不是小于) a[i]的数a[k](二分查找+RMQ某段区间的最小值是否小于a[i].最后确定到一个点),于是
我们可以得到在区间[i,k-1]范围内的数都会大于 a[i] ,所以对于下标i,它对应的最长区间必定在[i,k-1]之间。
所以,我们只要找到这个区间最大值 a[j] (这里又要用到RMQ查找区间最大值下标) 所以我们可以得到相对于点 i,其对应的最长子区间是[i,j]
例: 2 3 4 5 3 2 6 7
我们先枚举下标1 ,算出 右边不大于它的点是 a[6] = 2
然后对于 区间 2 3 4 5 3 2 最大值是 a[4] = 5 ,所以相对于下标1最长的区间是 1 - 4,依此类推。
http://poj.org/problem?id=2452
题意:在区间[1,n]上找到满足 a[i]<a[k]<a[j] (i<=k<=j) 的最大子区间 (j-i)如不存在输出 -1.
思路:枚举i,找到 i右边第一个不大于(不是小于) a[i]的数a[k](二分查找+RMQ某段区间的最小值是否小于a[i].最后确定到一个点),于是
我们可以得到在区间[i,k-1]范围内的数都会大于 a[i] ,所以对于下标i,它对应的最长区间必定在[i,k-1]之间。
所以,我们只要找到这个区间最大值 a[j] (这里又要用到RMQ查找区间最大值下标) 所以我们可以得到相对于点 i,其对应的最长子区间是[i,j]
例: 2 3 4 5 3 2 6 7
我们先枚举下标1 ,算出 右边不大于它的点是 a[6] = 2
然后对于 区间 2 3 4 5 3 2 最大值是 a[4] = 5 ,所以相对于下标1最长的区间是 1 - 4,依此类推。
#include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; const int N = 50005; ///储存区间最大最小值的下标 int max_dp[2*N][30]; int min_dp[2*N][30]; int a ; int MAX(int i,int j){ if(a[i]>a[j]) return i; return j; } int MIN(int i,int j){ if(a[i]>a[j]) return j; return i; } void init_RMQ(int n){ for(int i=1;i<=n;i++){ max_dp[i][0] = min_dp[i][0]=i; } for(int j=1;(1<<j)<=n;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ max_dp[i][j] = MAX(max_dp[i][j-1],max_dp[i+(1<<(j-1))][j-1]); min_dp[i][j] = MIN(min_dp[i][j-1],min_dp[i+(1<<(j-1))][j-1]); } } } int MAX_RMQ(int l,int r){ int k = (int)(log(r-l+1.0)/log(2.0)); return MAX(max_dp[l][k],max_dp[r-(1<<k)+1][k]); } int MIN_RMQ(int l,int r){ int k = (int)(log(r-l+1.0)/log(2.0)); return MIN(min_dp[l][k],min_dp[r-(1<<k)+1][k]); } int binary(int value,int l,int r){ while(l<=r){ if(l==r) return l; int mid = (l+r)>>1; //printf("MIN_RMQ:%d\n",a[MIN_RMQ(l,mid)]); if(value<a[MIN_RMQ(l,mid)]){ l = mid+1; }else r = mid; } } int main() { int n; while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } init_RMQ(n); int ans = 0; for(int i=1;i<=n;i++){ int value = a[i]; int k = binary(value,i+1,n); int j = MAX_RMQ(i,k); //printf("%d %d %d\n",i,k,j); if(a[j]>a[i]) ans = ans>j-i?ans:j-i; } if(ans==0) printf("-1\n"); else printf("%d\n",ans); } }
相关文章推荐
- Android开发 调用系统相机和加载图片到本地的使用
- HttpClient学习
- 图像处理中一阶微分的等式证明
- 后缀求可重叠最长重复子串
- HDU 5656
- 2016/04/03练习赛(2)
- 如何熟悉一个开源项目?
- Dubbo高级篇_03_Redis的安装与使用
- Ubuntu启动出错相关
- LeetCode OJ刷题历程——Maximum Depth of Binary Tree
- 使用myeclipse开发Servlet
- python语言学习7——数据类型和变量
- 内核分析-第六周
- JavaScript之变量与常量
- 【BZOJ1588】【HNOI2002】营业额统计
- 文件的切割与合并
- Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflow
- 设计模式之设计原则-单一职责原则
- Linux系统创建一个新的进程
- 备忘