codeforces 846D Monitor (二分+二维前缀和)

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 × kconsisting 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

PS:题意:在一个n*m的平面上,有n*m个点。但是有一些点,在某个时间后有一些点要损坏,现在求能使一个k*K平面内所有点都是损坏的最短时间,不存在这个时间输出-1。

题解:先二分一个答案,在判断这个时间的时候是否有满足题意。再判断的时候用前缀和。在判断用 二分的答案时。声明一个二维数组,把在这个时间以前坏的点都赋值为1,其他赋值为0。然后用前缀和判断是否有一个大小为K*K的范围内,数组的所有和都为1,若是有,直接继续二维,直到找到最小时间,要是二分结束后没有,直接输出-1。(注意在数组中横竖方向是反过来的)

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=5e2+10;
const int mod=1e9+7;
const int inf=1e9;
#define me(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
typedef long long ll;
using namespace std;
struct node
{
    int x,y,t;
}a[maxn*maxn];
int cnt[maxn][maxn],n,m,k,p;
int check(int mid)
{
    me(cnt,0);//赋初值。
    for(int i=1;i<=p;i++)
        if(a[i].t<=mid)
            cnt[a[i].y][a[i].x]=1;//说明在该时间前该点已经坏掉了。
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            cnt[i][j]+=cnt[i-1][j]+cnt[i][j-1]-cnt[i-1][j-1];
            if(i>=k&&j>=k&&cnt[i][j]-cnt[i-k][j]-cnt[i][j-k]+cnt[i-k][j-k]==k*k)//判断是否有平面满足
                return 1;
        }
    return 0;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&k,&p);
    for(int i=1;i<=p;i++)
        scanf("%d%d%d",&a[i].y,&a[i].x,&a[i].t);//在数组中方向横竖相反的。
    int l=-1,r=inf+1;
    while(l+1<r)//不能是“<=”,那样因为下面没有mid赋值时没有减一。
    {
        int mid=(l+r)>>1;
        if(check(mid))
            r=mid;
        else
            l=mid;
    }
    if(r==inf+1)
        cout<<"-1"<<endl;
    else
        cout<<r<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41292370/article/details/84978535