题面来自m大的网站 https://www.malic.xyz/
二维前缀和大家应该都懂吧,然后枚举每一个位置,对这个位置右下方的每一行进行二分,求每一行的第一个列坐标满足这个矩阵内1的个数大于等于k。
时间复杂度n^3log(N),常数比较小。本地测了一下极限数据跑了半秒,应该能过,问了一下xyx大佬,大佬说枚举位置之后可以尺取做,我大概get到了吧哈哈哈,不想写了(其实是不会)
样例过了我就没再测,希望各位大佬能给找找错。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e3 + 10; const int inf = 0x3f3f3f3f; int dis[4][2] = {1, 0, 0, 1, 0, -1, -1, 0}; int r, c, n, k; int sum[maxn][maxn]; int a[maxn][maxn]; int check(int x1, int y1, int p, int L) { int R = c; int x2 = p, y2 = R; int mid, ans = 0; if (sum[x2][y2] + sum[x1 - 1][y1 - 1] - sum[x1 - 1][y2] - sum[x2][y1 - 1] < k) { return -1; } while (L <= R) { int mid = (L + R) >> 1; y2 = mid; if (sum[x2][y2] + sum[x1 - 1][y1 - 1] - sum[x1 - 1][y2] - sum[x2][y1 - 1] >= k) { ans = mid; R = mid - 1; } else { L = mid + 1; } } return c - ans + 1; } int main() { #ifdef WXY freopen("in.txt", "r", stdin); #endif double dur; // clock_t start, end; // start = clock(); cin >> r >> c >> n >> k; for (int i = 0; i < n; i++) { int x, y; cin >> x >> y; a[x][y] = 1; } for (int i = 1; i <= r; i++) { for (int j = 1; j <= c; j++) { sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j]; } } long long ans = 0; for (int i = 1; i <= r; i++) { for (int j = 1; j <= c; j++) { for (int p = i; p <= r; p++) { int t = check(i, j, p, j); ans = ans + (t == -1 ? 0 : t); } } } cout << ans << "\n"; // end = clock(); // dur = (double)(end - start); // printf("Use Time:%f\n", (dur / CLOCKS_PER_SEC)); return 0; }