• 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;
    }
  • 相关阅读:
    java多线程练习题 类
    java练习题在一个文件里面输入内容在另一个文件里面可以查看
    java练习题输入流姓名学号信息
    java 异常处理2
    java 处理异常练习题
    java get银行练习题
    java 练习题 求梯形的面积和周长
    java get正确写类的练习题 猫
    GUID 全局唯一标识符
    oracle 建表 练习2
  • 原文地址:https://www.cnblogs.com/zhang1107/p/3026053.html
Copyright © 2020-2023  润新知