Challenge: Farmer

Subdomeniu: Combinatorics (combinatorics)

Scor cont: 80.0 / 80

Submission status: Accepted

Submission score: 1.0

Submission ID: 464763378

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/demidenko-farmer/problem

Cerinta

The farmer decided to build a barn on his farm. But on his farm there are trees and other buildings, which he does not want to remove.   

For simplicity, we represent the farm as a rectangular grid of height $N$ and width $M$. Each of the trees and buildings are located in one or more cells of the grid. The barn is a rectangle and should be built on the free cells of the grid.   

Help the farmer to find out how many ways there are to place the barn, for all possible sizes of barns.  

**Input Format**  
The first line contains two integers $N$ and $M$ - the dimensions of the farm.  
The next $N$ lines contains description of the farm: each line contains $M$ characters - `0` or `1` (`1` means the cell is available/free for building the barn).  

**Output Format**  
Write $N$ lines with $M$ integers in each line. The $j^{th}$ value in the $i^{th}$ line must be equal to the number of ways to place a barn with height $i$ and width $j$ in the farm.  

**Constraints**  
$1 \le N, M \le 1024$  

**Sample input**  

    3 3
    011
    110
    110

**Sample Output**  

    6 3 0
    3 1 0
    1 0 0

**Explanation**

Barns with height 1 and width 1:

    0*1    01*    011    011    011    011
    110    110    *10    1*0    110    110
    110    110    110    110    *10    1*0

Barns with height 1 and width 2:

    0**    011    011
    110    **0    110
    110    110    **0

Barns with height 2 and width 1:

    0*1    011    011
    1*0    *10    1*0
    110    *10    1*0
    
Barns with height 2 and width 2 (there is only one):

    011
    **0
    **0
    
Barns with height 3 and width 1 (there is only one):

    0*1
    1*0
    1*0

<sub>Time Limits: C/C++ 1 sec, Java/C# 2 sec, other languages follow standard TL given in [Environment](https://hackerrank.com/environment)</sub>

Cod sursa

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, M;
    if (!(cin >> N >> M)) return 0;

    int W = (M + 63) >> 6;
    int rem = M & 63;
    uint64_t lastMask = (rem == 0 ? ~0ULL : ((1ULL << rem) - 1ULL));

    vector<vector<uint64_t>> rows(N, vector<uint64_t>(W, 0));
    for (int i = 0; i < N; ++i) {
        string s;
        cin >> s;
        for (int j = 0; j < M; ++j) {
            if (s[j] == '1') rows[i][j >> 6] |= (1ULL << (j & 63));
        }
    }

    vector<vector<long long>> diffA(N + 1, vector<long long>(M + 2, 0));
    vector<vector<long long>> diffB(N + 1, vector<long long>(M + 2, 0));

    auto addRun = [&](int h, int L) {
        // For widths w in [1..L], add (L-w+1) = (-1)*w + (L+1)
        diffA[h][1] -= 1;
        diffA[h][L + 1] += 1;
        diffB[h][1] += (L + 1);
        diffB[h][L + 1] -= (L + 1);
    };

    vector<uint64_t> cur(W);

    for (int top = 0; top < N; ++top) {
        for (int w = 0; w < W; ++w) cur[w] = rows[top][w];
        if (W > 0) cur[W - 1] &= lastMask;

        for (int bot = top; bot < N; ++bot) {
            if (bot > top) {
                bool any = false;
                for (int w = 0; w < W; ++w) {
                    cur[w] &= rows[bot][w];
                    if (cur[w]) any = true;
                }
                if (W > 0) cur[W - 1] &= lastMask;
                if (!any) continue;
            }

            int h = bot - top + 1;
            int carry = 0;

            for (int w = 0; w < W; ++w) {
                uint64_t u = cur[w];
                int bits = (w == W - 1 && rem != 0) ? rem : 64;
                uint64_t full = (bits == 64) ? ~0ULL : ((1ULL << bits) - 1ULL);

                if (u == 0) {
                    if (carry) {
                        addRun(h, carry);
                        carry = 0;
                    }
                    continue;
                }
                if (u == full) {
                    carry += bits;
                    continue;
                }

                for (int b = 0; b < bits; ++b) {
                    if ((u >> b) & 1ULL) {
                        ++carry;
                    } else if (carry) {
                        addRun(h, carry);
                        carry = 0;
                    }
                }
            }
            if (carry) addRun(h, carry);
        }
    }

    for (int h = 1; h <= N; ++h) {
        long long a = 0, b = 0;
        for (int w = 1; w <= M; ++w) {
            a += diffA[h][w];
            b += diffB[h][w];
            long long ans = a * w + b;
            if (w > 1) cout << ' ';
            cout << ans;
        }
        cout << '\n';
    }

    return 0;
}
HackerRank Combinatorics – Farmer