Monitor CodeForces-846D (two-dimensional prefix and + two points)

Recently Luba bought a monitor. Monitor is a rectangular matrix of size n × m. But then she started to notice that some pixels cease to work properly. Luba thinks that the monitor will become broken the first moment when it contains a square k × k consisting entirely of broken pixels. She knows that q pixels are already broken, and for each of them she knows the moment when it stopped working. Help Luba to determine when the monitor became broken (or tell that it’s still not broken even after all q pixels stopped working).

Input
The first line contains four integer numbers n, m, k, q (1 ≤ n, m ≤ 500, 1 ≤ k ≤ min(n, m), 0 ≤ q ≤ n·m) — the length and width of the monitor, the size of a rectangle such that the monitor is broken if there is a broken rectangle with this size, and the number of broken pixels.

Each of next q lines contain three integer numbers xi, yi, ti (1 ≤ xi ≤ n, 1 ≤ yi ≤ m, 0 ≤ t ≤ 109) — coordinates of i-th broken pixel (its row and column in matrix) and the moment it stopped working. Each pixel is listed at most once.

We consider that pixel is already broken at moment ti.

Output
Print one number — the minimum moment the monitor became broken, or “-1” if it’s still not broken after these q pixels stopped working.

Examples
Input
2 3 2 5
2 1 8
2 2 8
1 2 1
1 3 4
2 3 2
Output
8
Input
3 3 2 5
1 2 2
2 2 1
2 3 5
3 2 10
2 1 100
Output
-1

Two-dimensional prefix and
meaning:
Given an n×m matrix, q points in it are broken. When all the points in a k × k sub-matrix in the entire matrix are broken, then the entire matrix is It will be damaged. The q points are damaged in a certain chronological order. It is judged at the earliest when the entire matrix will be damaged, that is, the points in the k × k sub-matrices are all damaged. If there is no damage to the entire matrix, output −1.
Problem solution idea:
Given the time when each point is damaged, the time is linear and monotonic, and the two-division time can be used to reduce the time complexity.
First, we sort the q points in chronological order from smallest to largest, and divide the time into two. For each time mid, we use a two-dimensional array mp to accumulate all points damaged within mid time by 1, and then add 1 to the array a Find the prefix sum again, then find the prefix sum on the array a, and finally enumerate the k × k sub-matrix in the whole graph, and query the number of damaged points in the sub-matrix. If the number is equal to k × k, then mid is feasible.

AC code:
PS: Note that the data range of q is n*m

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<map>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<set>
#include<cctype>
#include<string>
#include<stdexcept>
#include<fstream>
#define mem(a,b) memset(a,b,sizeof(a))
#define debug() puts("what the fuck!")
#define debug(a) cout<<#a<<"="<<a<<endl;
#define speed {
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); };
#define ll long long
#define mod 998244353
using namespace std;
const double PI = acos(-1.0);
const int maxn = 5e2 + 10;
const int INF = 0x3f3f3f3f;
const double esp_0 = 1e-6;
ll gcd(ll x, ll y) {
    
    
	return y ? gcd(y, x % y) : x;
}
ll lcm(ll x, ll y) {
    
    
	return x * y / gcd(x, y);
}
ll extends_gcd(ll a, ll b, ll& x, ll& y) {
    
    
	if (b == 0) {
    
    
		x = 1;
		y = 0;
		return a;
	}
	ll gcdd=extends_gcd(b, a % b, x, y);
	ll temp = x;
	x = y;
	y = temp - (a / b) * y;
	return gcdd;
}
struct node {
    
    
	int x, y, t;
	friend bool operator<(const node& a, const node& b) {
    
    
		return a.t < b.t;
	}
}a[maxn * maxn];
int mp[maxn][maxn];
int sum[maxn][maxn];
int n, m, k, q;
int judge(int time) {
    
    
	mem(mp, 0);
	mem(sum, 0);
	for (int i = 0; i < q; ++i) {
    
    
		if (a[i].t <= time)mp[a[i].x][a[i].y] = 1;
	}
	for (int i = 1; i <= n; ++i) {
    
    
		for (int j = 1; j <= m; ++j) {
    
    
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mp[i][j];//求二维前缀和
		}
	}
	for (int i = k; i <= n; ++i) {
    
    
		for (int j = k; j <= m; ++j) {
    
    
		//判断每一个k*k的子矩阵,注意下标是K
			if (sum[i][j] - sum[i - k][j] - sum[i][j - k] + sum[i - k][j - k] == k * k) {
    
    
				return 1;
			}
		}
	}
	return 0;
}
int main(){
    
    
	scanf("%d%d%d%d", &n, &m, &k, &q);
	int left = 0, right = 0, mid = 0;
	for (int i = 0; i < q; ++i) {
    
    
		scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].t);
		right = max(right, a[i].t);
	}
	sort(a, a + q);
	int ans = INF;
	while (left <= right) {
    
    
		mid = (left + right) >> 1;
		if (judge(mid)) {
    
    
			ans = mid;
			right = mid - 1;
		}
		else
			left = mid + 1;
	}
	if (ans == INF) {
    
    
		ans = -1;
	}
	printf("%d\n", ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_40924271/article/details/109911905