码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1047 [HAOI2007]理想的正方形

时间:2015-12-30 21:47:51      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

【看了题解才会做

这是一个典型的二维滑动窗口问题~

二维滑动窗口问题的处理方法可以类比一维滑动窗口的处理方法

首先将矩阵分解成B个列,对这B个列分别用单调队列维护一个长度为N的一维滑动窗口。记录colmax[i][j]为第j列第i行的元素(即第j个列的第i个元素)到第j列第i-N+1的元素(即第j个列的第i-N+1个元素)的最大值。这个用单调队列随便维护一下就好啦~

然后将矩阵分解成A个行,对这A个行再分别用单调队列维护一个长度为N的一维滑动窗口。记录rowmax[i][j]为colmax[i][j]~colmax[i][j-N+1]的最大值。显然地,此时rowmax[i][j]就是第i行第j列的元素到第i-N+1行第j-N+1列的元素(二维的)的最大值。

然后再做一遍最小值的。最后扫描一遍就可以啦~

 

技术分享
  1 #include <deque>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 void Get_Val(int &Ret)
  9 {
 10     Ret = 0;
 11     char ch;
 12     while ((ch = getchar()), (ch > 9 || ch < 0))
 13         ;
 14     do
 15     {
 16         (Ret *= 10) += ch - 0;
 17     }
 18     while ((ch = getchar()), (ch >= 0 && ch <= 9));
 19 }
 20 
 21 const size_t Max_AB(1050);
 22 
 23 int A, B;
 24 int N;
 25 int Value[Max_AB][Max_AB];
 26 
 27 int colmax[Max_AB][Max_AB], rowmax[Max_AB][Max_AB];
 28 int colmin[Max_AB][Max_AB], rowmin[Max_AB][Max_AB];
 29 
 30 void init()
 31 {
 32     Get_Val(A), Get_Val(B), Get_Val(N);
 33     for (int i = 1;i <= A;++i)
 34         for (int j = 1;j <= B;++j)
 35             Get_Val(Value[i][j]);
 36 }
 37 
 38 struct node
 39 {
 40     node(const int &a = 0, const int &b = 0) : Number(a), Value(b) {}
 41     int Number;
 42     int Value;
 43 };
 44 
 45 void Col_Max(int col[][Max_AB])
 46 {
 47     deque<node> Q;
 48     for (int j = 1;j <= B;++j)
 49     {
 50         Q.clear();
 51         for (int i = 1;i <= A;++i)
 52         {
 53             while (!Q.empty() && Q.back().Value < Value[i][j])
 54                 Q.pop_back();
 55             Q.push_back(node(i, Value[i][j]));
 56             if (Q.front().Number < i - N + 1)
 57                 Q.pop_front();
 58             col[i][j] = Q.front().Value;
 59         }
 60     }
 61 }
 62 
 63 void Row_Max(int col[][Max_AB], int row[][Max_AB])
 64 {
 65     deque<node> Q;
 66     for (int i = 1;i <= A;++i)
 67     {
 68         Q.clear();
 69         for (int j = 1;j <= B;++j)
 70         {
 71             while (!Q.empty() && Q.back().Value < col[i][j])
 72                 Q.pop_back();
 73             Q.push_back(node(j, col[i][j]));
 74             if (Q.front().Number < j - N + 1)
 75                 Q.pop_front();
 76             row[i][j] = Q.front().Value;
 77         }
 78     }
 79 }
 80 
 81 void work()
 82 {
 83     Col_Max(colmax);
 84     Row_Max(colmax, rowmax);
 85     for (int i = 1;i <= A;++i)
 86         for (int j = 1;j <= B;++j)
 87             Value[i][j] = -Value[i][j];
 88     Col_Max(colmin);
 89     Row_Max(colmin, rowmin);
 90 }
 91 
 92 void Get_Ans()
 93 {
 94     int Ans(0X7F7F7F7F);
 95     for (int i = N;i <= A;++i)
 96         for (int j = N;j <= B;++j)
 97             Ans = min(Ans, rowmax[i][j] + rowmin[i][j]);
 98     printf("%d", Ans);
 99 }
100 
101 int main()
102 {
103     init();
104     work();
105     Get_Ans();
106     return 0;
107 }
BZOJ 1047

 

BZOJ 1047 [HAOI2007]理想的正方形

标签:

原文地址:http://www.cnblogs.com/Created-equal/p/5089962.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!