#include<iostream> #include<cstdio> #include<cmath> usingnamespace std; #define MAXN 200010 constint N_N=log2(MAXN)+2; int n,k; int d[MAXN][N_N]; int a[MAXN]; inlineintmax(int a, int b){ return a > b ? a : b; }
voidst(){ int m, i, j; for(int i=1;i<=n;i++) d[i][0]=a[i]; //m = (int) (log((double) n) / log(2.0)); m=log2(n); for (j = 1; j <= m; ++j) { for (i = 1; i + (1 << j) - 1 <= n; ++i) d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]); } }
intrmq(int a, int b){ int m = (int) (log(b - a + 1.0) / log(2.0)); returnmax(d[a][m], d[b - (1 << m) + 1][m]); } intmain() { while(~scanf("%d",&n)){ for(int i=1;i<=n;i++)scanf("%d",&a[i]); int t; st(); scanf("%d",&t); while(t--){ int a,b; scanf("%d%d",&a,&b); printf("%d\n",rmq(a,b)); } } return0; }
二维RMQ
两种做法:
O(nmlog(m))-O(n)
O(nmlog(n)log(m)-O(1)
第一种很好理解。
把每一行都当成一维RMQ处理
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<set> #include<vector> #include<map> #include<queue> #include<set> #include<algorithm> usingnamespace std; #define MAXN 250 int dp[MAXN][MAXN][20]; int dp1[MAXN][MAXN][20]; int a[MAXN][MAXN]; int n,m; voidst(){ for(int i=1;i<=n;i++) for(int k=0;(1<<k)<=m;k++){ for(int j=1;j+(1<<k)-1<=m;j++){ if(k==0){ dp[i][j][k]=dp1[i][j][k]=a[i][j]; } else { dp[i][j][k]=max(dp[i][j][k-1],dp[i][j+(1<<(k-1))][k-1]); dp1[i][j][k]=min(dp1[i][j][k-1],dp1[i][j+(1<<(k-1))][k-1]); } } } } intrmq2dmax(int x,int y,int x1,int y1){ int k=log2(y1-y+1); int mm=max(dp[x][y][k],dp[x][y1-(1<<k)+1][k]); for(int i=x+1;i<=x1;i++) mm=max(mm,max(dp[i][y][k],dp[i][y1-(1<<k)+1][k])); return mm; } intrmq2dmin(int x,int y,int x1,int y1){ int k=log2(y1-y+1); int mm=min(dp1[x][y][k],dp1[x][y1-(1<<k)+1][k]); for(int i=x+1;i<=x1;i++) mm=min(mm,min(dp1[i][y][k],dp1[i][y1-(1<<k)+1][k])); return mm; }