Recientemente, Luba compró un monitor. El monitor es una matriz rectangular de tamaño n × m. Pero luego comenzó a notar que algunos píxeles dejan de funcionar correctamente. Luba cree que el monitor se romperá en el primer momento cuando contenga un cuadrado k × k que consiste enteramente en píxeles rotos. Sabe que los q píxeles ya están rotos, y para cada uno de ellos sabe el momento en que dejó de funcionar. Ayude a Luba a determinar cuándo se rompió el monitor (o dígale que aún no está roto incluso después de que todos los q píxeles dejaron de funcionar).
Entrada
La primera línea contiene cuatro números enteros n, m, k, q (1 ≤ n, m ≤ 500, 1 ≤ k ≤ min (n, m), 0 ≤ q ≤ n · m) - la longitud y el ancho del monitor, el tamaño de un rectángulo tal que el monitor se rompa si hay un rectángulo roto con este tamaño, y el número de píxeles rotos.
Cada una de las siguientes q líneas contiene tres números enteros xi, yi, ti (1 ≤ xi ≤ n, 1 ≤ yi ≤ m, 0 ≤ t ≤ 109) - coordenadas del i-ésimo píxel roto (su fila y columna en la matriz) y en el momento en que dejó de funcionar. Cada píxel se muestra como máximo una vez.
Consideramos que el píxel ya está roto en el momento ti.
Salida
Imprima un número: el momento mínimo en que el monitor se rompió, o "-1" si aún no está roto después de que estos q píxeles dejaron de funcionar.
Ejemplos
Entrada
2 3 2 5
2 1 8
2 2 8
1 2 1
1 3 4
2 3 2
Salida
8
Entrada
3 3 2 5
1 2 2
2 2 1
2 3 5
3 2 10
2 1100
Salida
-1
Prefijo bidimensional y
significado:
Dada una matriz n × m, q puntos en ella están rotos. Cuando todos los puntos en una submatriz k × k en la matriz completa están rotos, entonces toda la matriz está dañada. Los q puntos están dañados en un cierto orden cronológico, se juzga como más temprano cuando se daña toda la matriz, es decir, todos los puntos de las submatrices k × k están dañados. Si no hay daño en toda la matriz, salida −1.
Idea para la solución del problema:
dado el momento en que se daña cada punto, el tiempo es lineal y monótono, y el tiempo de dos divisiones se puede utilizar para reducir la complejidad del tiempo.
Primero, clasificamos los q puntos en orden cronológico de menor a mayor, y dividimos el tiempo en dos. Para cada tiempo mid, usamos una matriz bidimensional mp para acumular todos los puntos dañados dentro del tiempo medio por 1, y luego sumamos 1 a la matriz a Encuentre la suma del prefijo nuevamente, luego encuentre la suma del prefijo en la matriz a, y finalmente enumere la submatriz k × k en todo el gráfico, y consulte el número de puntos dañados en la submatriz. Si el número es igual a k × k, entonces mid es factible.
Código de CA:
PS: tenga en cuenta que el rango de datos de q es 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;
}