1. 程式人生 > >codeforces 846D Monitor (二分+二維字首和)

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 x

i, 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;
}