zoukankan      html  css  js  c++  java
  • 「AHOI2014/JSOI2014」拼图

    「AHOI2014/JSOI2014」拼图

    传送门
    看到 (n imes 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
    ", ans);
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        int T; read(T);
        while (T--) solve();
        return 0;
    }
    
  • 相关阅读:
    最长回文子串
    学习与提升
    jupyter notebook nginx 试听录音文件,网页试听
    【神经网络】batch、epoch、iteration的含义
    【tensorflow】Tensorflow入门教程
    最全BAT面试题
    打印二叉树
    基于argparser模块实现 ls 功能(基本实现)
    比较详细的argpasrse模块的基本使用
    ini文件转换为Json文件
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12260647.html
Copyright © 2011-2022 走看看