RMQ [POJ3368Frequent values]

http://poj.org/problem?id=3368

一维RMQ

View Code
//询问递增序列 [l,r] 间,出现次数最多的数的个数,分段后用RMQ询问最小值
int id, d[MM][17], N, Q;
int len[MM],pos[MM],b[MM];

int log_2(int x) {
    int res=0;
    while(x>>=1) res++;
    return res;
}
void get_rmq() {
    int i,j,k,limit;
    for(i=1;i<=id;i++) d[i][0]=len[i];
    k=log_2(id);
    for(i=1;i<=k;i++) {
        limit=id-(1<<i)+1;
        for(j=1;j<=limit;j++) {
            d[j][i]=max(d[j][i-1],d[j+(1<<i>>1)][i-1]);
        }
    }
}
void get_data() {
    int i,j,k,a,pre=maxint;
    scanf("%d",&Q);
    memset(len,0,sizeof(len));
    for(i=id=0;i<N;i++) {
        scanf("%d",&a);
        if(a!=pre) id++,pre=a,b[id]=i;;
        pos[i]=id;
        len[id]++;
    }
    get_rmq();
    for(i=1;i<=id;i++) b[i]+=len[i];
}
//query
int query(int ll,int rr) {
    int k=log_2(rr-ll+1);
    return max(d[ll][k],d[rr-(1<<k)+1][k]);
}

void solve() {
    int i,j,k,l,r;
    while(Q--) {
        scanf("%d%d",&l,&r);
        l--,r--;
        if(pos[l]==pos[r])  printf("%d\n",r-l+1);
        else if(pos[l]+1==pos[r])    printf("%d\n",max(b[pos[l]]-l,r-b[pos[l]]+1));
        else {
            int mi=query(pos[l]+1,pos[r]-1);
            int tmp=max(b[pos[l]]-l,r-b[pos[r]-1]+1);
            printf("%d\n",max(tmp,mi));
        }
    }
}

int main() {
    while(scanf("%d",&N),N) get_data(),solve();
    return 0;
}

 二维RMQ

View Code
const int MM = 305;
int n, m;
bool flag;
int maze[MM][MM];
int dp[MM][MM][9][9];
int id[MM];

int Log_2(int x) {
  int res = 1, cnt = 0;
  while(res <= x) res <<= 1,cnt++;
  return cnt-1;
}

void get_data() {
  for(int i = 1;i <= n; i++)
      for(int j = 1;j <= m; j++) 
          scanf("%d",&maze[i][j]);
}

void get_init() {
  id[0] = -1;
  for(int i = 1;i < MM;i++) 
      id[i] = Log_2(i);
} 
/************************
二维RMQ的模版题
用dp[row][col][i][j]表示(row,col) 
到(row+2^i,col+2^j)的最小值
///////////////////////////////
查询时:
int kx = log_2(x2-x1+1);
int ky = log_2(y2-y1+1);
去下面四个的最小值:
int m1 = dp[x1][y1][kx][ky];
int m2 = dp[x2-(1<<kx)+1][y1][kx][ky];
int m3 = dp[x1][y2-(1<<ky)+1][kx][ky];
int m4 = dp[x2-(1<<kx)+1][y2-(1<<ky)+1][kx][ky];
*************************/
////////////////初始化/////////////
void init_Rmq() {
   int i, j, row, col, limt_row;
   
   for(i = 1;i <= n;i++) 
       for(j = 1;j <= m;j++)
           dp[i][j][0][0] = maze[i][j]; 

       int k1 = id[n], k2 = id[m];
       for(i = 0;i <= k1; i++) 
           for(j = 0;j <= k2; j++) {
               if(i==0 && j==0) continue;
               for(row = 1;row+(1<<i)-1 <= n;row++) { 
                   limt_row = row+(1<<(i-1));
                   for(col = 1;col+(1<<j)-1 <= m;col++) { 
                       if(i == 0) {
                         dp[row][col][i][j]=f_max(dp[row][col][i][j-1],dp[row][col+(1<<(j-1))][i][j-1]);
                       } else {
                          dp[row][col][i][j]=f_max(dp[row][col][i-1][j],dp[limt_row][col][i-1][j]);
                       }
                   }
               }
           }
}
///////////////////////询问最大值/////////////
int Query(int x1,int x2,int y1,int y2) {
  int kx = id[x2-x1+1]; 
  int ky = id[y2-y1+1];
  int xx2, yy2;
  xx2 = x2-(1<<kx)+1; yy2 = y2-(1<<ky)+1;
  int m1 = dp[x1][y1][kx][ky];
  int m2 = dp[xx2][y1][kx][ky];
  int m3 = dp[x1][yy2][kx][ky]; 
  int m4 = dp[xx2][yy2][kx][ky]; 
//  printf("%d %d %d\n",kx,ky,Log_2(1));
//  printf("%d %d %d %d\n",m1,m2,m3,m4);
  int ans= f_max(f_max(m1,m2),f_max(m3,m4)); 
  if(ans==maze[x1][y1] || ans==maze[x1][y2] || ans==maze[x2][y1] || ans==maze[x2][y2]) flag = true;
  return ans;
}
//////////////////////////////////////
void solve() {
   int q, x1, y1, x2, y2;
   init_Rmq();
   scanf("%d", &q);
   while(q--) {
      flag = false;
      scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
      printf("%d ",Query(x1,x2,y1,y2));
      puts(flag?"yes":"no");
   }
}
 
int main() {
    get_init();
    while(scanf("%d%d",&n,&m)!=EOF) get_data(),solve();
 return 0;
}
原文地址:https://www.cnblogs.com/zhang1107/p/3026053.html