Algorithm Solutions: Grid Patterns, Matrix Transformations, and Pairing Problems

Tile Pattern

Problem: We have a 10^9×10^9 grid where each cell's color is determined by (i%n, j%n). We're given an n×n character matrix and need to answer q queries about the number of black cells in specified rectangular regions.

Solution: We use a 2D prefix sum approach to efficiently count black cells in any rectangle.


#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

const int MAX_SIZE = 1024;
int gridSize;
ll prefixSum[MAX_SIZE][MAX_SIZE];

ll countBlackCells(int x, int y) {
    ll completeBlocks = (x / gridSize) * (y / gridSize) * prefixSum[gridSize][gridSize];
    ll partialBottomRight = prefixSum[x % gridSize][y % gridSize];
    ll partialBottomLeft = prefixSum[x % gridSize][gridSize] * (y / gridSize);
    ll partialTopRight = prefixSum[gridSize][y % gridSize] * (x / gridSize);
    
    return completeBlocks + partialBottomRight + partialBottomLeft + partialTopRight;
}

int main() {
    int queries;
    cin >> gridSize >> queries;
    
    vector<vector>> pattern(gridSize + 1, vector<char>(gridSize + 1));
    
    for (int i = 1; i <= gridSize; i++) {
        for (int j = 1; j <= gridSize; j++) {
            cin >> pattern[i][j];
            prefixSum[i][j] = (pattern[i][j] == 'B') + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1];
        }
    }
    
    while (queries--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        x2++; y2++;
        
        ll result = countBlackCells(x2, y2) - countBlackCells(x1, y2) - countBlackCells(x2, y1) + countBlackCells(x1, y1);
        cout << result << '\n';
    }
}
</char></vector></vector></iostream>

Matrix Transformation Puzzle

Problem: Given two h×w matrices, determine if we can transform the first into the second using adjacent row and column swaps. If possible, find the minimum number of swaps required.

Solution: We genearte all possible row and column permutations of the second matrix and check if any matches the first matrix. The minimum number of swaps is determined by counting inversions in the permutation sequences.


#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

int originalMatrix[6][6], targetMatrix[6][6];
int rowPermutations[250][6], colPermutations[250][6];
int rows, cols, totalRowPerms, totalColPerms;
bool visited[10];
int tempPermutation[10];

void generateRowPermutations(int current) {
    if (current > rows) {
        memcpy(rowPermutations[++totalRowPerms], tempPermutation, sizeof(tempPermutation));
        return;
    }
    
    for (int i = 1; i <= rows; i++) {
        if (!visited[i]) {
            visited[i] = true;
            tempPermutation[current] = i;
            generateRowPermutations(current + 1);
            visited[i] = false;
        }
    }
}

void generateColPermutations(int current) {
    if (current > cols) {
        memcpy(colPermutations[++totalColPerms], tempPermutation, sizeof(tempPermutation));
        return;
    }
    
    for (int i = 1; i <= cols; i++) {
        if (!visited[i]) {
            visited[i] = true;
            tempPermutation[current] = i;
            generateColPermutations(current + 1);
            visited[i] = false;
        }
    }
}

bool isValidPermutation(int rowPermIdx, int colPermIdx) {
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= cols; j++) {
            if (originalMatrix[rowPermutations[rowPermIdx][i]][colPermutations[colPermIdx][j]] != targetMatrix[i][j]) {
                return false;
            }
        }
    }
    return true;
}

int countInversions(int permutation[], int size) {
    int inversions = 0;
    for (int i = 0; i < size - 1; i++) {
        for (int j = i + 1; j < size; j++) {
            if (permutation[i] > permutation[j]) {
                inversions++;
            }
        }
    }
    return inversions;
}

int main() {
    cin >> rows >> cols;
    
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= cols; j++) {
            cin >> originalMatrix[i][j];
        }
    }
    
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= cols; j++) {
            cin >> targetMatrix[i][j];
        }
    }
    
    // Check if matrices are already identical
    bool identical = true;
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= cols; j++) {
            if (originalMatrix[i][j] != targetMatrix[i][j]) {
                identical = false;
                break;
            }
        }
        if (!identical) break;
    }
    
    if (identical) {
        cout << 0 << endl;
        return 0;
    }
    
    // Generate all row and column permutations
    memset(visited, false, sizeof(visited));
    generateRowPermutations(1);
    memset(visited, false, sizeof(visited));
    generateColPermutations(1);
    
    int minSwaps = 1e8;
    
    for (int i = 1; i <= totalRowPerms; i++) {
        for (int j = 1; j <= totalColPerms; j++) {
            if (isValidPermutation(i, j)) {
                int totalSwaps = countInversions(rowPermutations[i], rows) + countInversions(colPermutations[j], cols);
                if (totalSwaps < minSwaps) {
                    minSwaps = totalSwaps;
                }
            }
        }
    }
    
    if (minSwaps != 1e8) {
        cout << minSwaps << endl;
    } else {
        cout << -1 << endl;
    }
}
</algorithm></cstring></vector></iostream>

Socks Pairing Problem

Problem: We have n pairs of socks, each pair having the same color (color i for pair i). After losing k socks, we want to pair the remaining socks to minimize the sum of absolute differences between paired socks' colors.

Solution: We use a greedy approach with prefix sums. To odd k, we need to cnosider which sock to exclude to minimize the total strangeness.


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

int sockColors[300000];
ll minStrangeness;

int main() {
    int n, k;
    cin >> n >> k;
    
    for (int i = 0; i < k; i++) {
        cin >> sockColors[i];
    }
    
    sort(sockColors, sockColors + k);
    
    if (k % 2 == 0) {
        // Even number of lost socks - straightforward pairing
        minStrangeness = 0;
        for (int i = 1; i < k; i += 2) {
            minStrangeness += sockColors[i] - sockColors[i-1];
        }
    } else {
        // Odd number of lost socks - need to decide which sock to exclude
        vector<ll> prefixSum(k);
        
        // Calculate prefix sums for odd indices
        for (int i = 1; i < k; i += 2) {
            prefixSum[i+1] = sockColors[i] - sockColors[i-1];
            if (i > 1) {
                prefixSum[i+1] += prefixSum[i-1];
            }
        }
        
        // Initialize with the case where the last sock is excluded
        minStrangeness = prefixSum[k-1];
        
        ll currentSum = 0;
        // Try excluding each sock at odd positions
        for (int i = k-2; i >= 0; i -= 2) {
            currentSum += sockColors[i+1] - sockColors[i];
            ll candidate = currentSum + (i > 0 ? prefixSum[i-1] : 0);
            if (candidate < minStrangeness) {
                minStrangeness = candidate;
            }
        }
    }
    
    cout << minStrangeness << endl;
}
</ll></algorithm></vector></iostream>

Tags: prefix-sums Permutations inversions greedy-algorithms matrix-transformation

Posted on Mon, 17 Aug 2026 16:54:20 +0000 by DrJonesAC2