poj 2452 RMQ(Sticks Problem)
2015-02-24 20:54
239 查看
题意:给出n个互不相同的数字,要求一个最大的子段,使得该子段内所有数(除了两端以外),值都在两端的数字之间(比左端值大,比右端值小)。
分析:(http://www.cnblogs.com/rainydays/archive/2012/07/10/2584576.html)先对整个数组分别构造最大值RMQ和最小值RMQ的数组。然后,枚举子段起点,对于每个起点求出这个起点是区间最小值的最远终点(用二分查找)。然后在这个区间内找到最大值位置,从起点到最大值位置这个区间就是起点所对应的符合题意的最大区间。枚举过所有的起点之后,结果就求出来了。其中二分还是比较灵活。如果不用hash的话,那么rmq的时候保存下标而不是值即可。
discuss里有人说单调栈甚至暴搜也能AC。
不用hash,rmq保存下标:
分析:(http://www.cnblogs.com/rainydays/archive/2012/07/10/2584576.html)先对整个数组分别构造最大值RMQ和最小值RMQ的数组。然后,枚举子段起点,对于每个起点求出这个起点是区间最小值的最远终点(用二分查找)。然后在这个区间内找到最大值位置,从起点到最大值位置这个区间就是起点所对应的符合题意的最大区间。枚举过所有的起点之后,结果就求出来了。其中二分还是比较灵活。如果不用hash的话,那么rmq的时候保存下标而不是值即可。
discuss里有人说单调栈甚至暴搜也能AC。
#include <stdio.h> #include <string.h> #include <math.h> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define N 50005 int dmax [20],dmin [20],s ,hash[100005]; int n; void st(){ int i,j; int k = log((double)n+1)/log(2.0); for(i = 1;i<=n;i++) dmax[i][0] = dmin[i][0] = s[i]; for(j = 1;j<=k;j++) for(i = 1;i+(1<<j)-1<=n;i++) dmax[i][j] = max(dmax[i][j-1], dmax[i+(1<<(j-1))][j-1]), dmin[i][j] = min(dmin[i][j-1], dmin[i+(1<<(j-1))][j-1]); } int querymin(int a,int b){ int k = log((double)(b-a+1))/log(2.0); return min(dmin[a][k], dmin[b-(1<<k)+1][k]); } int querymax(int a,int b){ int k = log((double)(b-a+1))/log(2.0); return max(dmax[a][k], dmax[b-(1<<k)+1][k]); } int search(int x,int low,int high){ int j,mid; int base = low-1; while(low <= high){ mid = (low+high)>>1; j = querymin(base,mid); if(j < x) high = mid-1; else low = mid+1; } return high; } int main(){ while(scanf("%d",&n) != EOF){ int i,j,end,res=0; memset(hash,0,sizeof(hash)); for(i = 1;i<=n;i++){ scanf("%d",&s[i]); hash[s[i]] = i;//由于这些数各不相同,所以可以用hash } st(); for(i = 1;i<n;i++){ end = search(s[i],i+1,n);//这个二分还是比较灵活的 j = hash[querymax(i,end)]-i; res = max(res,j); } printf("%d\n",(!res)?-1:res); } return 0; }
不用hash,rmq保存下标:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50005 #define M 100005 int s ,n,dmin [20],dmax [20]; void st(int n){ int i,j,k = log((double)n)/log(2.); for(i = 1;i<=n;i++) dmin[i][0] = dmax[i][0] = i; for(j = 1;j<=k;j++) for(i = 1;i+(1<<j)-1<=n;i++){ if(s[dmin[i][j-1]] < s[dmin[i+(1<<(j-1))][j-1]]) dmin[i][j] = dmin[i][j-1]; else dmin[i][j] = dmin[i+(1<<(j-1))][j-1]; if(s[dmax[i][j-1]] > s[dmax[i+(1<<(j-1))][j-1]]) dmax[i][j] = dmax[i][j-1]; else dmax[i][j] = dmax[i+(1<<(j-1))][j-1]; } } int qmax(int a,int b){ int k = log((double)(b-a+1))/log(2.); if(s[dmax[a][k]] < s[dmax[b-(1<<k)+1][k]]) return dmax[b-(1<<k)+1][k]; return dmax[a][k]; } int qmin(int a,int b){ int k = log((double)(b-a+1))/log(2.); if(s[dmin[a][k]] > s[dmin[b-(1<<k)+1][k]]) return dmin[b-(1<<k)+1][k]; return dmin[a][k]; } int search(int b,int low,int high){ int mid; while(low <= high){ mid = (low+high)>>1; if(s[qmin(low,mid)] < b) high = mid-1; else low = mid+1; } return high; } int main(){ while(scanf("%d",&n)!=EOF){ int i,j; int res = -1; for(i = 1;i<=n;i++) scanf("%d",&s[i]); st(n); for(i = 1;i<n;i++){ j = search(s[i],i+1,n); int tmp = qmax(i,j); res = max(res,tmp-i); } printf("%d\n",!res?-1:res); } return 0; }
相关文章推荐
- poj-2452 Sticks Problem(二分+RMQ)
- POJ 2452 Sticks Problem(二分+RMQ)
- POJ 2452 Sticks Problem [RMQ+二分]
- POJ 2452 Sticks Problem (暴力或者rmq+二分)
- POJ 2452 Sticks Problem(二分+RMQ)
- POJ 2452 Sticks Problem(RMQ+二分)
- poj2452 Sticks Problem RMQ问题
- 【RMQ】POJ 2452
- POJ2452---Sticks Problem(单调栈+RMQ,方法不够优秀)
- POJ 2452 Sticks Problem
- POJ 2452 Sticks Problem
- POJ 2452 Sticks Problem ★ (单调栈+RMQ)
- POJ 2452 Sticks Problem ★ (单调栈+RMQ)
- poj 2452(RMQ+二分)
- poj 2452 Sticks Problem
- poj2452——Sticks Problem
- POJ2452 && BNU2571:Sticks Problem
- POJ 2452 Sticks Problem (线段树+递归)
- POJ 2452 Sticks Problem(ST+二分查找)
- POJ 2452 Sticks Problem (RMQ + 预处理)