zoukankan      html  css  js  c++  java
  • 【cf1262E】E. Arson In Berland Forest(二分+二维差分)

    传送门

    题意:
    现有一张(ncdot m,ncdot mleq 10^6)的网格图,一开始有些初始火点,之后每一秒火点都会向周围八个格子蔓延。
    现已知最终火点分布情况。
    要求构造出一个原始火点图,使得经过(T)秒后能够到达该终态,并且(T)尽可能大。

    思路:
    显然最后答案具有单调性,那么我们直接二分时间(T)
    若存在一个格子为火点,那么终态((2T+1)cdot (2T+1))大小的矩形都会成为火点,根据这一点我们预处理二维前缀和找到所有最后可能成为火点的位置。
    之后根据这些位置来(check)是否覆盖所有火点即可。
    (check)时也需要用到二维前缀和。
    代码可能写得有点乱:

    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/3 15:02:46
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    int n, m;
    char s[N];
     
    bool chk(vector<vector<int>>& res, vector<vector<int>>& mp, vector<vector<ll>>& a, ll T) {
        T = 2 * T + 1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                res[i][j] = 0;
            }   
        }
        vector <vector <ll>> c(n, vector <ll> (m, 0));
        auto ask = [&] (int r1, int c1, int r2, int c2) {
            ll ans = a[r2][c2];
            if(r1) ans -= a[r1 - 1][c2];
            if(c1) ans -= a[r2][c1 - 1];
            if(r1 && c1) ans += a[r1 - 1][c1 - 1];
            return ans == T * T;
        };
        
        for(int i = 0; i + T - 1 < n; i++) {
            for(int j = 0; j + T - 1 < m; j++) {
                if(ask(i, j, i + T - 1, j + T - 1)) {
                    ++c[i][j];
                    if(i + T < n) --c[i + T][j];
                    if(j + T < m) --c[i][j + T];
                    if(i + T < n && j + T < m) ++c[i + T][j + T];
                    res[i + T / 2][j + T / 2] = 1;
                }
            }
        }
        for(int i = 0; i < n; i++) {
            for(int j = 1; j < m; j++) {
                c[i][j] += c[i][j - 1];
            }   
        }
        for(int i = 1; i < n; i++) {
            for(int j = 0; j < m; j++) {
                c[i][j] += c[i - 1][j];
            }   
        }
        
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(mp[i][j] > 0 && c[i][j] <= 0) return false;
            }   
        }
        return true;
    }
     
    void run() {
        cin >> n >> m;
        vector <vector<int>> a(n, vector<int> (m)), b(n, vector <int> (m)), c(n, vector <int> (m));
        vector <vector <ll>> sum(n, vector <ll> (m));
        for(int i = 0; i < n; i++) {
            cin >> s;
            for(int j = 0; j < m; j++) {
                a[i][j] = (s[j] == 'X' ? 1 : 0);
            }   
        }
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                sum[i][j] = a[i][j];
                if(i) sum[i][j] += sum[i - 1][j];
                if(j) sum[i][j] += sum[i][j - 1];
                if(i && j) sum[i][j] -= sum[i - 1][j - 1];
            }   
        }
        int l = 0, r = n * m + 1, mid;
        while(l < r) {
            mid = (l + r) >> 1;
            if(chk(b, a, sum, mid)) {
                l = mid + 1;
                c = b;
            }
            else r = mid;
        }
        cout << l - 1 << '
    ';
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                if(c[i][j]) cout << 'X';
                else cout << '.';
            }
            cout << '
    ';
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    linux设备驱动程序第3版学习笔记(例程3--scull)未完1
    linux设备驱动程序第3版学习笔记(例程2--hellop.c)
    linux设备驱动程序第3版学习笔记(例程1)
    Intellij中request等对象无法解析
    OneNote学习笔记----语言概述
    四、归并排序(mergesort)
    三、堆排序(Heapsort),优先队列可以用于O(N log N)
    二、希尔排序(Shellsort)-- 缩减增量排序(diminishing increment sort)
    一、插入排序(insertion sort)
    hashmap冲突的解决方法以及原理分析:
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12451563.html
Copyright © 2011-2022 走看看