zoukankan      html  css  js  c++  java
  • BZOJ 1047

    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3686  Solved: 2037
    [Submit][Status][Discuss]

    Description

      有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
    的差最小。

    Input

      第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
    行相邻两数之间用一空格分隔。
    100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

    Output

      仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

    Sample Input

    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2

    Sample Output

    1
     
    好久没写题了。。。
    我可是要冲省队的呀!!!
     
    这道题嘛就二维单调队列,理解起来并不难
    先搞定一维的再加另一重循环应该能减少调试时间(可惜我没有意识到调了半天)
    另外按列来看的时候要注意分清到底是哪一维再操作
     
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define N 1005
    using namespace std;
    int a,b,n,lmax=1,rmax,lmin=1,rmin;
    int m[N][N],qmax[N],qmin[N],tmax[N][N],tmin[N][N],amax[N][N],amin[N][N];
    int main()
    {
        scanf("%d%d%d",&a,&b,&n);
        for(int i=1;i<=a;i++)
            for(int j=1;j<=b;j++)
                scanf("%d",&m[i][j]);
        
        for(int i=1;i<=a;i++)
        {
            lmax=1;rmax=0;
            memset(qmax,0,sizeof(qmax));
            for(int j=1;j<=b;j++)
            {
                while(lmax<=rmax && qmax[lmax]<=j-n)lmax++;
                while(lmax<=rmax && m[i][j]>=m[i][qmax[rmax]])rmax--;
                qmax[++rmax]=j;tmax[i][j]=m[i][qmax[lmax]];
            }
            /*
            for(int k=1;k<=a;k++)printf("%d ",tmax[i][k]);
            printf("
    ");
            */
            lmin=1;rmin=0;
            memset(qmin,0,sizeof(qmin));
            for(int j=1;j<=b;j++)
            {
                while(lmin<=rmin && qmin[lmin]<=j-n)lmin++;
                while(lmin<=rmin && m[i][j]<=m[i][qmin[rmin]])rmin--;
                qmin[++rmin]=j;tmin[i][j]=m[i][qmin[lmin]];
            }
        }
        /*
        printf("
    ");
        for(int i=1;i<=a;i++)
        {
            for(int j=1;j<=b;j++)
                printf("%d ",tmax[i][j]);
            printf("
    ");
        }
        printf("
    ");
        for(int i=1;i<=a;i++)
        {
            for(int j=1;j<=b;j++)
                printf("%d ",tmin[i][j]);
            printf("
    ");
        }
        */
        for(int i=1;i<=b;i++)
        {
            lmax=1;rmax=0;
            memset(qmax,0,sizeof(qmax));
            for(int j=1;j<=a;j++)
            {
                while(lmax<=rmax && qmax[lmax]<=j-n)lmax++;
                while(lmax<=rmax && tmax[j][i]>=tmax[qmax[rmax]][i])rmax--;
                qmax[++rmax]=j;amax[j][i]=tmax[qmax[lmax]][i];
            }
            /*
            for(int k=1;k<=a;k++)printf("%d ",amax[k][i]);
            printf("
    ");
            */
            lmin=1;rmin=0;
            memset(qmin,0,sizeof(qmin));
            for(int j=1;j<=a;j++)
            {
                while(lmin<=rmin && qmin[lmin]<=j-n)lmin++;
                while(lmin<=rmin && tmin[j][i]<=tmin[qmin[rmin]][i])rmin--;
                qmin[++rmin]=j;amin[j][i]=tmin[qmin[lmin]][i];
            }
        }
        /*
        printf("
    ");
        for(int i=1;i<=a;i++)
        {
            for(int j=1;j<=b;j++)
                printf("%d ",amax[i][j]);
            printf("
    ");
        }
        printf("
    ");
        for(int i=1;i<=a;i++)
        {
            for(int j=1;j<=b;j++)
                printf("%d ",amin[i][j]);
            printf("
    ");
        }
        */
        int ans=1000000000;
        for(int i=n;i<=a;i++)
            for(int j=n;j<=b;j++)
                ans=min(ans,amax[i][j]-amin[i][j]);
        printf("%d",ans);
        
    //    system("pause");
        return 0;
    }
  • 相关阅读:
    $.each
    KBASP.NET 2.0 網站部署的變革
    详尽解析window.event对象
    Jquery1.2.6 源码分析
    索引学习2聚族索引、非聚族索引、组合索引
    在C#中使用WIA获取扫描仪数据
    Adobe Photoshop CS5简体中文版+完美破解方法
    j2me开发图片加载
    数据库操作
    WPF之DataGrid应用
  • 原文地址:https://www.cnblogs.com/fdfzhyf/p/7912010.html
Copyright © 2011-2022 走看看