当前位置:首页 > Web开发 > 正文

(bt - tp + 1) * (rmmx.first + mid + lmx.first));}return res

2024-03-31 Web开发

标签:

「AHOI2014/JSOI2014」拼图

传送门
看到 \(n \times m \le 10^5\) ,考虑根号分治。
对付 \(n < m\) 的情况,我们可以枚举最终矩形的上下界限 \(tp, bt\),那么我们发明最终矩形必然是由所有满足从第 \(tp\) 行到第 \(bt\) 行都是白格子的矩形按序连接,并且两端再各自接上一个最大的前缀和一个最大的后缀组成的。
这个我们可以 \(O(m)\) 地算。
总庞大度就是 \(O(n^2m)\),也就是一个根号级另外。
对付 \(n \ge m\) 的情况,我们必定不能还去枚举上下界限,但是此时我们可以对付每一个白色的格子,都找一个它上面的最远的一个白格子来组成一组上下界限,然后套用第一问的计算要领就好了。
预措置惩罚惩罚是 \(O(nm)\) 的,总庞大度是 \(O(nm^2)\),还是一个根号级另外。
还有一个坑点就是再找前、后缀矩形时要制止反复使用一个矩阵,所以我们还得记录次大值。
参考代码:

#include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout) template < class T > inline T max(T a, T b) { return a > b ? a : b; } template < class T > inline void read(T& s) { s = 0; int f = 0; char c = getchar(); while ('0' > c || c > '9') f |= c == '-', c = getchar(); while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar(); s = f ? -s : s; } const int _ = 1e5 + 5; int s, n, m, l[_], r[_], lr[_], a[_], sum[_], up[_]; struct node { int first, second; } lmx, lmmx, rmx, rmmx; inline int id(int i, int j) { return i != 0 && j != 0 ? (j - 1) * n + i : 0; } inline int S(int x1, int y1, int x2, int y2) { return sum[id(x2, y2)] - sum[id(x2, y1 - 1)] - sum[id(x1 - 1, y2)] + sum[id(x1 - 1, y1 - 1)]; } inline int calc(int tp, int bt) { int res = 0; for (rg int i = 1; i <= s; ++i) for (rg int ss = 0, j = l[i]; j <= r[i]; ++j) { if (S(tp, j, bt, j) != 0) ss = 0; else ++ss; res = max(res, (bt - tp + 1) * ss); } int mid = 0; lmx = lmmx = rmx = rmmx = (node) { 0, 0 }; for (rg int i = 1; i <= s; ++i) { int ls = 0, rs = 0; for (rg int j = l[i]; j <= r[i]; ++j) if (S(tp, j, bt, j) != 0) break ; else ++ls; for (rg int j = r[i]; j >= l[i]; --j) if (S(tp, j, bt, j) != 0) break ; else ++rs; if (ls == lr[i]) mid += lr[i]; else { if (ls > lmx.first) lmmx = lmx, lmx = (node) { ls, i }; else if (ls > lmmx.first) lmmx = (node) { ls, i }; if (rs > rmx.first) rmmx = rmx, rmx = (node) { rs, i }; else if (rs > rmmx.first) rmmx = (node) { rs, i }; } } if (lmx.second != rmx.second) res = max(res, (bt - tp + 1) * (lmx.first + mid + rmx.first)); else { res = max(res, (bt - tp + 1) * (lmmx.first + mid + rmx.first)); res = max(res, (bt - tp + 1) * (rmmx.first + mid + lmx.first)); } return res; } inline void solve() { read(s), read(n), m = 0; for (rg int i = 1; i <= s; ++i) { read(lr[i]), l[i] = m + 1, m += lr[i], r[i] = m; for (rg int j = 1; j <= n; ++j) for (rg int k = l[i]; k <= r[i]; ++k) scanf("%1d", a + id(j, k)); } for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= m; ++j) sum[id(i, j)] = sum[id(i - 1, j)] + sum[id(i, j - 1)] - sum[id(i - 1, j - 1)] + a[id(i, j)]; int ans = 0; if (n < m) { for (rg int i = 1; i <= n; ++i) for (rg int j = i; j <= n; ++j) ans = max(ans, calc(i, j)); } else { for (rg int j = 1; j <= m; ++j) { for (rg int p = 0, i = 1; i <= n; ++i) { if (a[id(i, j)] != 0) { for (rg int k = p + 1; k < i; ++k) up[id(k, j)] = p; p = i; } for (rg int k = p + 1; k <= n; ++k) up[id(k, j)] = p; } } for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= m; ++j) if (a[id(i, j)] == 0) ans = max(ans, calc(up[id(i, j)] + 1, i)); } printf("%d\n", ans); } int main() { #ifndef ONLINE_JUDGE file("cpp"); #endif int T; read(T); while (T--) solve(); return 0; }

「AHOI2014/JSOI2014」拼图

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/30539.html