题目
题目描述
你有 qq 个相同颜色的颜料,和一个 nn 行 mm 列的棋盘。
你计划在棋盘上涂 qq 个格子,对于第 ii 个要涂的格子,用 (x_i, y_i,t_i)(xi,yi,ti) 表示 在 t_iti 时刻涂一个位于 (Xi, Yi)(xi,yi) 的格子。
问,最早什么时候棋盘上会形成一个边长至少为 kk 的正方形。
输入格式
第一行有 4个整数, n, m, k,q(1 <= n,m<= 500, 1 <=k <=min(n,m), 0<=q <=n*m)n,m,k,q(1≤n,m≤500,1≤k≤min(n,m),0≤q≤n∗m)。
接下来的 qq 行,每行三个整数 Xi,Yi, Ti(1 <= Xi <= n, 1 <= y_i <= m, 0 <= t <= 10^9 )xi,yi,ti(1≤xi≤n,1≤yi≤m,0≤t≤109)。
输出格式
输出一个整数,表示棋盘上形成一个边长至少为 kk 的正方形的最早时刻,如果不存在输出 -1−1。
题目解析
本题采用前缀和+二分的思路,二分时间,根据时间的早晚将对应二维数组的值化为一,利用结构体把一组x,y,t储存起来,根据t小于check中的时间依次填入,在每次check时都要求一次前缀和,后利用所求前缀和求出给定边长的正方形,直到发现有num=k*k。
#include <bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl "\n"
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 510;
int n,m,k,q;
struct PIII
{
int x;
int y;
int t;
}p[N * N];
bool check(int x)
{
vector<vector<int>> a(n + 1,vector<int>(m + 1));
for(int i = 1; i <= q; i ++)
{
if(p[i].t > x) continue;
a[p[i].x][p[i].y] = 1;
// 判断时间的有效性
}
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
{
if(i + k - 1 > n || j + k - 1 > m) continue;
//找左上角的数字
int res = a[i + k - 1][j + k - 1] - a[i - 1][j + k - 1] - a[i + k -1][j - 1] + a[i - 1][j - 1];
if(res == k * k) return true;
}
return false;
}
void solve()
{
cin >> n >> m >> k >> q;
for(int i = 1; i <= q; i ++)
cin >> p[i].x >> p[i].y >> p[i].t;
int l = 0,r = 1e9;
while(l < r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
if(check(l)) cout << l << endl;
else cout << "-1" << endl;
return;
}
int main()
{
IOS;
int t = 1;
// cin >> t;
while(t --)
solve();
return 0;
}