zoukankan      html  css  js  c++  java
  • [HAOI2007]理想的正方形

    题目描述

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

    输入输出格式

    输入格式:

    第一行为3个整数,分别表示a,b,n的值

    第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

    输出格式:

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

    输入输出样例

    输入样例#1:
    5 4 2
    1 2 5 6
    0 17 16 0
    16 17 2 1
    2 10 2 1
    1 2 2 2
    
    输出样例#1:
    1

    说明

    问题规模

    (1)矩阵中的所有数都不超过1,000,000,000

    (2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

    (3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100

    先求出每列往前n个的最小值和最大值,然后在用这个东西求出二维的往前上方n*n的正方形的最大值和最小值.
    可以用一个set实时维护插入和删除,复杂度O(n^2log(n)).
    更优的做法:用两个单调队列维护,每次队首都是最大值或最小值,实时维护插入和删除,插入是从后面开始比他大或小的都删掉,维护单调性,因为每个点只会出入队一次,复杂度O(n^2).

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<string>
     6 #include<algorithm>
     7 #include<map>
     8 #include<complex>
     9 #include<queue>
    10 #include<stack>
    11 #include<cmath>
    12 #include<set>
    13 #include<vector>
    14 #define maxn 1100
    15 #define IT multiset<int>::iterator
    16 using namespace std;
    17 int mp[maxn][maxn],zx[maxn][maxn],zd[maxn][maxn],zx1[maxn][maxn],zd1[maxn][maxn];
    18 struct data{
    19   int head,tail,q[maxn],p[maxn];
    20   void clear(){head=1,tail=0;}
    21   void push1(int key,int id){
    22     while(head<=tail && q[tail]>key)tail--;
    23     q[++tail]=key,p[tail]=id;
    24   }
    25   void push2(int key,int id){
    26     while(head<=tail && q[tail]<key)tail--;
    27     q[++tail]=key,p[tail]=id;
    28   }
    29   void pop(int id){
    30     while(p[head]<=id && head<=tail) head++;
    31   }
    32   int front(){
    33     return q[head];
    34   }
    35 }q1,q2;
    36 int main(){
    37   int n,m,k;
    38   scanf("%d%d%d",&n,&m,&k);
    39   for(int i=1;i<=n;i++)
    40     for(int j=1;j<=m;j++)
    41       scanf("%d",&mp[i][j]);
    42   for(int i=1;i<=n;i++){
    43     q1.clear();
    44     q2.clear();
    45     for(int j=1;j<=k;j++)
    46       q1.push1(mp[i][j],j),q2.push2(mp[i][j],j);
    47     zx1[i][k]=q1.front();zd1[i][k]=q2.front();
    48     for(int j=k+1;j<=m;j++){
    49       q1.pop(j-k),q2.pop(j-k);
    50       q1.push1(mp[i][j],j);q2.push2(mp[i][j],j);
    51       zx1[i][j]=q1.front();zd1[i][j]=q2.front();
    52     }
    53   }
    54   for(int j=k;j<=m;j++){
    55     q1.clear();
    56     for(int i=1;i<=k;i++)
    57       q1.push1(zx1[i][j],i);
    58     zx[k][j]=q1.front();
    59     for(int i=k+1;i<=n;i++){
    60       q1.pop(i-k);
    61       q1.push1(zx1[i][j],i);
    62       zx[i][j]=q1.front();
    63     }
    64   }
    65   for(int j=k;j<=m;j++){
    66     q2.clear();
    67     for(int i=1;i<=k;i++)
    68       q2.push2(zd1[i][j],i);
    69     zd[k][j]=q2.front();
    70     for(int i=k+1;i<=n;i++){
    71       q2.pop(i-k);
    72       q2.push2(zd1[i][j],i);
    73       zd[i][j]=q2.front();
    74     }
    75   }
    76   int ans=2000000000;
    77   for(int i=k;i<=n;i++)
    78     for(int j=k;j<=m;j++)
    79       ans=min(ans,zd[i][j]-zx[i][j]);
    80   printf("%d",ans);
    81   return 0;
    82 }
  • 相关阅读:
    SWT的TableVierer的使用二(数据排序)
    SWT的TableVierer的使用一
    SWT的TreeVierer的使用
    SWT中一些细节的说明
    SWT中各种参数大全
    SWT的GridLayout一些参数解释
    SWT中的GridLayout(转)例子不错
    鼠标放到按钮上,实现的动画
    关于文字下方线消失的动画
    超出部分用省略号代替,鼠标放上去显示多余部分内容
  • 原文地址:https://www.cnblogs.com/pantakill/p/7502688.html
Copyright © 2011-2022 走看看