Py&hyh想脱单

Py&hyh想脱单

Description

总所周知,,py和hyh有十分浓烈的脱单意愿,但是非常不幸,在一个风和日丽的下午,他们穿越到一个没有妹子的世界,他必须回答一个问题才能回到本来的世界,这个问题是给出一个nm的矩阵,然后有q次操作,每一个操作,给出xi,yi,ti,表示在ti时刻摧毁(xi,yi)这个格子,然后他们要求出一个最早时刻,出现至少一个kk的矩阵被毁坏,注意:一个kk矩阵被毁坏的意思是某一个kk的矩阵中的每一个格子都被摧毁过一次或一次以上。聪明的acmer能帮他们回答这个问题吗(如果没人能ac这个题,就代表他们两个没有脱单的可能了哦)

Input

Input:采用多组输入第一行输入n,m,k,q,(1 ≤ n, m ≤ 500, 1 ≤ k ≤ min(n, m), 1 ≤ q ≤ n·m)分别代表nm的矩阵,kk的矩阵,和q次操作接下来q行每一行输入xi,yi,ti(1 ≤ xi ≤ n, 1 ≤ yi ≤ m, 0 ≤ t ≤ 1e6),代表,在ti这个时刻,xi,yi这个位置会被摧毁

Output

Out:输出一行,代表最早时刻出现至少一个k*k的矩阵被毁坏如果永远不存在这一个时刻,输出-1

Sample Input 1 

2 3 2 5
2 1 8
2 2 8
1 2 1
1 3 4
2 3 2

Sample Output 1

8

Sample Input 2 

3 3 2 5
1 2 2
2 2 1
2 3 5
3 2 10
2 1 100

Sample Output 2

-1

题目求的是出现至少一个k*k的矩阵被毁坏的最早时刻,可以想到时间越长,轰炸次数也是越多的,然后出现k*k的矩阵被毁坏的几率也是越大的,因此可以看出这是符合单调性的,所以可以用二分枚举时间mid,判断mid时间是否满足,若满足往前面时间找满足条件的更小的时间,若不满足则往后找。我感觉这题判断轰炸之后,是否存在1个k*k的矩阵才是难点,做法是mp【i】[j],1表示当前格子被轰炸了,0表示没有被轰炸,然后用sum[i][j]记录每个格子对应的左上方向(感觉更前缀和很相似,左上方向可以理解为是1<=列数<=j,1<=行数<=i这个范围内)被轰炸的格子数(也就是mp[I][J]为1的格子的数量),然后暴力枚举整个地图里k*k的矩阵,对一个k*k的矩阵用之前求的sum[][]数组求该矩阵内被轰炸的格子的数量,若等于k*k说明当前枚举的这个矩阵就是满足条件的矩阵。

#include<bits/stdc++.h>
using namespace std;
#define maxn 505
struct node
{
    int t,x,y;

}boom[maxn*maxn];
int mp[maxn][maxn],sum[maxn][maxn];
int n,m,k,q;
bool cmp(const node&a,const node&b)
{
    return a.t<b.t;
}
int query(int xa,int ya,int xb,int yb)
{
    return sum[xb][yb]-sum[xa-1][yb]-sum[xb][ya-1]+sum[xa-1][ya-1];
}
bool check(int t)
{
    for(int i=0;i<=n+1;i++)
        for(int j=0;j<=m+1;j++)
            mp[i][j]=sum[i][j]=0;
    for(int i=1;i<=q;i++)
    {
        if(boom[i].t<=t)
            mp[boom[i].x][boom[i].y]=1;
        else
            break;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            sum[i][j]=mp[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];

        }
    for(int i=1;i<=n-k+1;i++)
        for(int j=1;j<=m-k+1;j++)
        {
            int x=i,y=j,xx=i+k-1,yy=j+k-1;
            if((k*k)==query(x,y,xx,yy))
                return true;

        }
    return false;
}
int main()
{
    std::ios::sync_with_stdio(false);
    while(cin>>n>>m>>k>>q)
    {
        if(n==0&&m==0&&k==0&&q==0)
             break;
        for(int i=1;i<=q;i++)
        {

            cin>>boom[i].x>>boom[i].y>>boom[i].t;

        }
        sort(boom+1,boom+q+1,cmp);
        int ans=-1;
        int low=0,up=1000000+10,mid;
        while(low<=up)
        {
            mid=(low+up)/2;
            if(check(mid))
            {

                ans=mid;
                up=mid-1;
            }
            else
                low=mid+1;
        }
        cout<<ans<<endl;

    }

    return 0;

}
原文地址:https://www.cnblogs.com/eason9906/p/11754974.html