zoukankan      html  css  js  c++  java
  • BZOJ1047 [HAOI2007]理想的正方形 单调队列

    1047: [HAOI2007]理想的正方形

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4184  Solved: 2361
    [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
    题解:

      在各行通过单调队列维护第i行中以j为结尾的长度为n的区间的最大值maxn和最小值minn

      然后再在各列跑一边单调队列,求出所有n×n正方形区域的最大值和最小值之差

    /**************************************************************
        Problem: 1047
        User: mizersy
        Language: C++
        Result: Accepted
        Time:1940 ms
        Memory:13144 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1005;
    struct Node{
        int w,p;
    };
    Node high[N],low[N];
    int head1,head2,tail1,tail2;
    int maxn[N][N],minn[N][N];
    int a[N][N];
    int n,m,k;
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for (int i = 1;i <= n;++i){
            head1 = head2 = tail1 = tail2 = 0;
            for (int j = 1;j <= m;++j){
                scanf("%d",&a[i][j]);
                while(head1 < tail1 && high[tail1-1].w < a[i][j]) tail1--;
                while(head1 < tail1 && j - high[head1].p >= k) head1++;
                high[tail1++] = Node{a[i][j],j};
                if (j >= k) maxn[i][j] = high[head1].w;
                while(head2 < tail2 && low[tail2-1].w > a[i][j]) tail2--;
                while(head2 < tail2 && j - low[head2].p >= k)head2++;
                low[tail2++] = Node{a[i][j],j};
                if (j >= k) minn[i][j] = low[head2].w;
            }
        }
        int ans = 1e9+7;
        for (int j = k;j <= m;++j){
            head1 = head2 = tail1 = tail2 = 0;
            for (int i = 1;i <= n;++i){
                while(head1 < tail1 && high[tail1-1].w < maxn[i][j]) tail1--;
                while(head1 < tail1 && i - high[head1].p >= k) head1++;
                high[tail1++] = Node{maxn[i][j],i};
                while(head2 < tail2 && low[tail2-1].w > minn[i][j]) tail2--;
                while(head2 < tail2 && i - low[head2].p >= k) head2++;
                low[tail2++] = Node{minn[i][j],i};
                if (j >= k && i >= k){
                    ans = min(ans,high[head1].w - low[head2].w);
                }
            }
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    网络爬虫基础练习
    综合练习-词频统计
    组合数据类型
    【Hadoop】Hadoop综合大作业
    理解MapReduce操作
    Hadoop-熟悉常用的HDFS操作
    python-爬取中药信息
    Pytthon-数据结构化与保存
    python-爬取校园新闻首页的新闻
    python-爬虫基础
  • 原文地址:https://www.cnblogs.com/mizersy/p/9550507.html
Copyright © 2011-2022 走看看