题意:每次对矩阵进行更新,有一个时刻。然后问什么时候使得矩阵中有k * k的矩阵被更新了。
思路:二分时间,然后判断每一个时间是否复合,注意这里的时间不一定是连续的,所以需要离散化。每次判断的时候需要对进行重新操作,判断是否符合,用到了二维树状数组。
#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; #define fi first #define se second #define INF 0x3f3f3f3f #define clr(x,y) memset(x,y,sizeof x) #define PI acos(-1.0) #define ITER set<int>::iterator const int Mod = 1e9 + 7; const int maxn = 1000 + 10; const int N = 2; struct Node { bool operator <(const Node & t)const{return z < t.z;} int x,y,z; }a[maxn * maxn]; int b[maxn * maxn]; int tree[maxn][maxn]; inline lowbit(int x){return x & (-x);} void update(int x,int y,int val){for(int i = x; i < maxn;i += lowbit(i))for(int j = y;j < maxn; j += lowbit(j))tree[i][j] += val;} int get(int x,int y){int ret = 0;for(int i = x; i > 0; i -= lowbit(i))for(int j = y; j > 0; j -= lowbit(j))ret += tree[i][j];return ret;} int n,m,k,q; bool check(int ti) { int t = b[ti];clr(tree,0); for(int i = 1; i <= q; i ++) { if(a[i].z > t)break; // if(t == 8)cout << a[i].x << " -> " << a[i].y << " " << a[i].z << endl; update(a[i].x,a[i].y,1); } for(int i = k; i <= n;i ++) { for(int j = k; j <= m; j ++) { int temp = get(i,j) - get(i - k,j) - get(i,j - k) + get(i - k,j - k); // if(t == 8)cout << t << " " << i << " " << j << " " << temp << endl; if(temp >= k * k)return true; } } return false; } int main() { while( ~ scanf("%d%d%d%d",&n,&m,&k,&q)) { for(int i = 1; i <= q; i ++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);b[i] = a[i].z; } sort(a + 1,a + q + 1); sort(b + 1,b + q + 1);int len = unique(b + 1,b + q + 1) - b - 1; // for(int i = 1; i <= len;i ++)cout << b[i] << " ";puts(""); int l = 1,r = len;int ans = -1; while(l <= r) { int mid = (l + r) >> 1; if(check(mid))ans = mid,r = mid - 1;else l = mid + 1; } printf("%d\n",ans == -1 ? -1 : b[ans]); } return 0; }