o(1)记录一个矩阵

o(1)记录一个矩阵

代码:

bool check(int x){
    memset(dot, 0, sizeof(dot));
    int cnt = 0;
    //处理记矩阵扩展一行一列后的四个角的坐标
    //预处理 为使每个矩阵中的每个点权值在原先基础上+1
    for(int i = 1; i <= x; i++){
        dot[a[i].x1][a[i].y1] ++;
        dot[a[i].x2 + 1][a[i].y2 + 1] ++;
        dot[a[i].x1][a[i].y2 + 1] --;
        dot[a[i].x2 + 1][a[i].y1] --;
    }
    // 遍历 dot[i][j]就代表 被几个矩阵覆盖过 
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            dot[i][j] += dot[i][j - 1] + dot[i - 1][j] - dot[i - 1][j - 1];
            if(dot[i][j]) cnt++;
        }
    }
    return cnt == n * m;
}

 

例题

周周选妃

链接:https://ac.nowcoder.com/acm/contest/29320/K
来源:牛客网

今天是瓜瓜大王选妃的日子,所有 MM 排成了 n×mn \times mn×m 的方阵。

每次瓜瓜可以任意选择一个矩形区域,但是瓜瓜又希望能够雨露均沾,每个 MM 都能被选到。

瓜瓜会做 kkk 次选择,你需要告诉他一个最早的一个选择 tit_iti,自此 tit_iti 以后(包括 tit_iti)所有人都被选到过了。如果不存在,输出 −1-11。

思路:

 二分 每次o(1)标记选择矩阵#include<bits/stdc++.h>#define FF ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);

using namespace std;
const int N = 1e5 + 10;
int n,m,k;
int cnt;
int dot[1000][1000], c[1000];

struct node {
    int x1, x2, y1, y2;
}a[N];

bool check(int x){
    memset(dot, 0, sizeof(dot));
    int cnt = 0;
        //预处理 为使后面遍历 时每个矩阵内的点的权值都加1(这当于o(1)记录了一个矩阵 这样就不会超时了)
//如果有重叠那就是重叠数了 for(int i = 1; i <= x; i++){ dot[a[i].x1][a[i].y1] ++; dot[a[i].x2 + 1][a[i].y2 + 1] ++; dot[a[i].x1][a[i].y2 + 1] --; dot[a[i].x2 + 1][a[i].y1] --; } // 遍历 dot[i][j] 就是 该点被几个矩阵覆盖过 for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ dot[i][j] += dot[i][j - 1] + dot[i - 1][j] - dot[i - 1][j - 1]; if(dot[i][j]) cnt++; } } //如果所有点都被覆盖过 返回真 return cnt == n * m; } void solve() { cin >> n >> m >> k; int flag = 0; for(int i = 1; i <= k; i++){ cin >> a[i].x1 >> a[i].y1 >> a[i].x2 >> a[i].y2; } int l = 1; int r = k + 1;//二分答案 while(l < r){ int mid = (l + r) / 2; if(check(mid)) r = mid; else l = mid + 1; } if (r > k) cout << -1 << "\n"; else cout << r << "\n"; } int main(){ FF; int t = 1; while(t--){ solve(); } return 0; }

 

posted @ 2022-03-20 23:51  Yaqu  阅读(123)  评论(0)    收藏  举报