容斥 或者 单调栈 hihocoder #1476 : 矩形计数 和 G. Snake Rana 2017 ACM Arabella Collegiate Programming Contest

先说一个简单的题目(题目大意自己看去,反正中文):hihocoder上的:http://hihocoder.com/problemset/problem/1476

然后因为这个n和m的矩阵范围是1000,所以比较简单

 

然后我们说一下hihocoder上面的做法,首先,这题的做法是http://www.cnblogs.com/heimao5027/p/6738715.html的简化版本,因为颜色只有两种,所以和前面链接给的做法那样,用单调栈维护一下即可。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1000 + 5;
int n, m, k;
map<pair<int, int>, int> mp;
int color[maxn][maxn], h[maxn][maxn];
LL dp[maxn][maxn];

struct Point{
    int high, col;
};

int main(){
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= k; i++){
        int a, b; scanf("%d%d", &a, &b);
        mp[mk(a, b)] = 1;
        color[a][b] = 1;
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= m; j++){
            dp[i][j] = 0;
            h[i][j] = 0;
            if (color[i][j]) continue;
            h[i][j] = 1;
            if (color[i][j] == color[i - 1][j])
                h[i][j] += h[i - 1][j];
        }
    }
    LL ans = 0;
    for (int i = 1; i <= n; i++){
        stack<Point> stc;
        for (int j = 1; j <= m; j++){
            if (color[i][j] == 1){
                while (!stc.empty()) stc.pop();
                continue;
            }
            int lb = j;
            while (!stc.empty()){
                if (stc.top().high >= h[i][j]) {
                    lb = stc.top().col; stc.pop();
                }
                else break;
            }
            dp[i][j] += 1LL * h[i][j] * (j - lb + 1);
            //printf("h[%d][%d] = %d lb = %d add = %lld\n", i, j, h[i][j], lb, 1LL*h[i][j] * (j - lb + 1));
            stc.push(Point{h[i][j], lb});
            if (color[i][lb - 1] == 0) dp[i][j] += dp[i][lb - 1];
            ans += dp[i][j];
        }
    }
    cout << ans << endl;
    return 0;
}
View Code

 

 

对于GYM上的题目:http://codeforces.com/gym/101350/problem/G

这题的n和m的范围是10000,所以很难用这个方法,因为对于1e8,空间是绝对开不下的

 

posted @ 2017-05-08 22:09  知る奇迹に  阅读(590)  评论(0编辑  收藏  举报