先说一个简单的题目(题目大意自己看去,反正中文):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 ") 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 ", 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; }
对于GYM上的题目:http://codeforces.com/gym/101350/problem/G
这题的n和m的范围是10000,所以很难用这个方法,因为对于1e8,空间是绝对开不下的