首页 > 代码库 > BZOJ1047 [HAOI2007]理想的正方形

BZOJ1047 [HAOI2007]理想的正方形

昨天刷水累死蒟蒻了。。。

每天一到题解总还是要写的。。。于是就是这个了!

二维RMQ,第一反应是二维线段树,妥妥MLE + TLE

想起来去年市选小题有一道一模一样的,我当时就是写二维线段树,然后MLE0分、、、真是悲剧

 

发现长度是固定的为n,和动态规划的某个叫单调队列的优化很像:

先求出每一列的某个点向下n个数的最大/小值,然后求出每一行某个点向右的n个单调队列的最大/小值,方法依旧是单调队列。。。

程序写的很烦。。。是照抄网上的。。。(太烦了不想写呢><)

 

 1 /************************************************************** 2     Problem: 1047 3     User: rausen 4     Language: C++ 5     Result: Accepted 6     Time:1604 ms 7     Memory:16600 kb 8 ****************************************************************/ 9  10 #include <cstdio>11 #include <algorithm>12  13 using namespace std;14 const int N = 1005;15  16 int mp[N][N];17 int q[N][N], h[N], t[N], Q[N];18 int mx[N][N], mn[N][N];19 int s, e, a, b, n;20  21 inline int read(){22     int x = 0, sgn = 1;23     char ch = getchar();24     while (ch < 0 || ch > 9){25         if (ch == -) sgn = -1;26         ch = getchar();27     }28     while (ch >= 0 && ch <= 9){29         x = x * 10 + ch - 0;30         ch = getchar();31     }32     return sgn * x;33 }34  35 void getmax(){36     for (int i = 1; i <= b; ++i)37         h[i] = 1, t[i] = 0;38     for (int i = 1; i <= a; ++i){39         for (int j = 1; j <= b; ++j){40             while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j];41             while (h[j] <= t[j] && mp[q[j][t[j]]][j] <= mp[i][j]) --t[j];42             q[j][++t[j]] = i;43         }44         e = 0, s = 1;45         for (int j = 1; j <= b; ++j){46             while (s <= e && j - Q[s] >= n) ++s;47             while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] <= mp[q[j][h[j]]][j]) --e;48             Q[++e] = j;49             mx[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]];50         }51     }52 }53  54 void getmin(){55     for (int i = 1; i <= b; ++i)56         h[i] = 1, t[i] = 0;57     for (int i = 1; i <= a; ++i){58         for (int j = 1; j <= b; ++j){59             while (h[j] <= t[j] && i - q[j][h[j]] >= n) ++h[j];60             while (h[j] <= t[j] && mp[q[j][t[j]]][j] >= mp[i][j]) --t[j];61             q[j][++t[j]] = i;62         }63         e = 0, s = 1;64         for (int j = 1; j <= b; ++j){65             while (s <= e && j - Q[s] >= n) ++s;66             while (s <= e && mp[q[Q[e]][h[Q[e]]]][Q[e]] >= mp[q[j][h[j]]][j]) --e;67             Q[++e] = j;68             mn[i][j] = mp[q[Q[s]][h[Q[s]]]][Q[s]];69         }70     }71 }72  73 int main(){74     a = read(), b = read(), n = read();75     for (int i = 1; i <= a; ++i)76         for (int j = 1; j <= b; ++j)77             mp[i][j] = read();78      79     getmax();80     getmin();81     int ans = (int) 1e9;82     for (int i = n; i <= a; ++i)83         for (int j = n; j <= b; ++j)84             ans = min(ans, mx[i][j] - mn[i][j]);85     printf("%d\n", ans);86     return 0;87 }
View Code

 

BZOJ1047 [HAOI2007]理想的正方形