1. 程式人生 > >[HAOI2007]修築綠化帶

[HAOI2007]修築綠化帶

inf lan d+ 窗口 isdigit 參考 綠化 %d ret

這道題要用到“尺取法”(又名“滑動窗口算法”),具體的描述可參考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 }

[HAOI2007]修築綠化帶