Py&hyh想脱单

原题地址:http://csustacm.com:4803/problem/1013

Description

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

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

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

思路:二分可以达到的时间,然后判断某一个区间是否被炸毁就用二维前缀和判断就行了.

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e6 + 5;
int n, m, k, q;
struct node {
    int x, y, t;
} e[maxn];
bool cmp(node a, node b) {
    return a.t < b.t;
}
int sum[505][505];//二维前缀和
int mp[505][505];//图
bool solve(int x, int y) {//求区间内的数的多少,要注意显示
    int ans = sum[x + k - 1][y + k - 1] + sum[x - 1][y - 1] - sum[x + k - 1][y - 1] - sum[x - 1][y + k - 1];
    if(ans == k * k) return 1;
    else return 0;
}
bool check(int mid) {
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            mp[i][j] = sum[i][j] = 0;
        }
    }
    for(int i = 1; i <= q; ++i) {
        if(e[i].t > mid) break;
        int x = e[i].x;
        int y = e[i].y;
        mp[x][y] = 1;
    }
    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) {
            if(solve(i, j)) return 1;
        }
    }
    return 0;
}
int main() {
    while(~scanf("%d%d%d%d", &n, &m, &k, &q)) {
        for(int i = 1; i <= q; ++i) {
            scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].t);
        }
        sort(e + 1, e + 1 + q, cmp);
        int left = 0;
        int right = 1e6;
        while(left <= right) {
            int mid = (left + right) / 2;
            if(check(mid)) right = mid - 1;
            else left = mid + 1;
        }
        if(right == 1e6) printf("-1\n");
        else printf("%d\n", left);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81582769