• 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;
    
    }
    
  • 相关阅读:
    int a=5,则 ++(a++)的值是?
    C中文件操作说明
    最大子序列和 o(n)
    括号匹配
    DOM、SAX、JDOM、DOM4J四种XML解析方法PK
    java中的trim()
    SAX解析XML
    ConcurrentHashMap完全解析(jdk6/7,8)
    为什么推荐Zookeeper作注册中心
    分布式锁的三种实现方式
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754974.html
Copyright © 2020-2023  润新知