zoukankan      html  css  js  c++  java
  • bzoj1057 [ZJOI2007]棋盘制作

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1057

    【题解】

    把网格图黑白染色,把原来的颜色异或黑白染色的颜色,就变成求最大0/1子矩形/正方形

    以最大全1子矩形为例。

    我们设a[i,j]表示第i行第j个之前有多少个连续的1。

    那么我们维护a单调上升的单调栈

    每次加入一个元素,如果比前面大等直接做,小的话更新答案,(这个元素到前面那个元素的一大段都能达到前面那个元素的a值)

    注意更新完答案,要更新位置值,这个值为这次更新最后一个出栈的那个位置。

    (因为我可以连续更新到那里啊。。这一大段都行)

    所以就行了。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 2e3 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    int n, m, ans1, ans2;
    int mp[M][M], a[M][M];
    int stn;
    struct pa {
        int x, h; 
        pa() {}
        pa(int x, int h) : x(x), h(h) {}
    }st[M];
    
    inline int sqr(int x) {
        return x*x;
    }
    
    inline void doit(int pos, int H) {
        int pre = pos;
        while(stn && st[stn].h > H) {
            ans1 = max(ans1, (pos-st[stn].x)*st[stn].h);
            ans2 = max(ans2, sqr(min(pos-st[stn].x, st[stn].h)));
            pre = st[stn].x;
            --stn;
        }
        st[++stn] = pa(pre, H);
    }
    
    inline void getans() {
        for (int i=1; i<=n; ++i) 
            for (int j=1; j<=m; ++j) 
                if(mp[i][j] == 0) a[i][j] = 0;
                else a[i][j] = a[i][j-1] + 1; 
        for (int i=1; i<=m; ++i) {
            stn = 0;
            for (int j=1; j<=n; ++j)
                doit(j, a[j][i]);
            doit(n+1, 0);
        }
    }
    
    int main() {
        cin >> n >> m;
        for (int i=1; i<=n; ++i) 
            for (int j=1; j<=m; ++j) { 
                scanf("%d", &mp[i][j]);
                int c = (i+j)&1;
                mp[i][j] ^= c; 
            }
        
    //    for (int i=1; i<=n; ++i, cout << endl) 
    //        for (int j=1; j<=m; ++j) cout << mp[i][j];  
    
        getans();
        
        for (int i=1; i<=n; ++i) 
            for (int j=1; j<=m; ++j) 
                mp[i][j] ^= 1; 
        
        getans(); 
        
        cout << ans2 << endl << ans1 << endl;
        
        return 0;
    }
    View Code
  • 相关阅读:
    转:马云邮件全文
    XIFF资料1
    代码还是请一个字母一个字母敲(如果您只想混口饭吃就不要读了本文只面向想成为hacker的程序员)
    一个本来很有希望的项目噶然而止,脑子一下子空了
    转:进京感受一个技术人职业发展心得
    java中定义接口
    两个大数相乘(纯C实现)
    [ios学习入门1]hello,word!
    两台电脑通信的连接过程
    谁说引用不可改变
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj1057.html
Copyright © 2011-2022 走看看