[HAOI2007]修筑绿化带

这道题要用到“尺取法”(又名“滑动窗口算法”),具体的描述可参考P2716 【和谐的雪花】——AC-Evil的洛谷博客

这道题跟上面的这题几乎一样。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define re register
 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
 7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
 8 #define maxx(a, b) a = max(a, b);
 9 #define minn(a, b) a = min(a, b);
10 #define LL long long
11 #define inf (1 << 30)
12 
13 inline int read() {
14     int w = 0, f = 1; char c = getchar();
15     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
17     return w * f;
18 }
19 
20 const int maxn = 1e3 + 5;
21 
22 int N, M, A, B, C, D, s[maxn][maxn], g[maxn][maxn];
23 int q[maxn], h, t;
24 #define square(x1, y1, x2, y2) (s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])
25 
26 int main() {
27     N = read(), M = read(), A = read(), B = read(), C = read(), D = read();
28     rep(i, 1, N)
29         rep(j, 1, M)
30             s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + read();
31     rep(i, C, N) {
32         h = t = 0;
33         rep(x, D, M) {
34             while (h < t && x-q[h] >= B-D-1) h++;
35             while (h < t && square(i-C+1, x-D+1, i, x) < square(i-C+1, q[t-1]-D+1, i, q[t-1])) t--;
36             q[t++] = x;
37             g[i][x] = square(i-C+1, q[h]-D+1, i, q[h]);
38         }
39     }
40     int ans = 0;
41     rep(i, B-1, M-1) {
42         h = t = 0;
43         rep(x, C, N-1) {
44             while (h < t && x-q[h] >= A-C-1) h++;
45             while (h < t && g[x][i] < g[q[t-1]][i]) t--;
46             q[t++] = x;
47             if (x-A+2>0)
48                 maxx(ans, square(x-A+2, i-B+2, x+1, i+1) - g[q[h]][i]);
49         }
50     }
51 
52     printf("%d", ans);
53 
54     return 0;
55 }

 

posted @ 2019-02-03 20:15  AC-Evil  阅读(218)  评论(0编辑  收藏  举报