Submission #878965

#TimeUsernameProblemLanguageResultExecution timeMemory
878965charleehpPaint By Numbers (IOI16_paint)C++14
100 / 100
1081 ms110472 KiB
#include "paint.h"

#include <cstdlib>
#include <iostream>

#define MAX_N 200000
#define MAX_K 100

int n, k;
std::string S;
std::vector<int> C;
int W[MAX_N], B[MAX_N];

bool memoLeft[MAX_N][MAX_K];
bool memoRight[MAX_N][MAX_K];
bool visLeft[MAX_N][MAX_K];
bool visRight[MAX_N][MAX_K];

bool possible[MAX_N][MAX_K];

int whiteInRange(int a, int b) {
    int sum = W[b];
    if (a)
        sum -= W[a - 1];
    return sum;
}

bool noBlacksInRange(int a, int b) {
    int sum = B[b];
    if (a)
        sum -= B[a - 1];
    return sum == 0;
}

bool canPlace(int i, int b) {
    if (i < 0)
        return false;

    // white space before  i
    if (i > 0 && S[i - 1] == 'X')
        return false;

    // all black spaces 
    if (i + C[b] > n)
        return false;

    if (whiteInRange(i, i + C[b] - 1))
        return false;

    // white space after end of block
    if (i <= n - 1 && S[i + C[b]] == 'X')
        return false;

    return true;
}

bool solLeft(int i, int b) {
    if (i >= n) 
        return b == k;
    
    if (b == k)
        return noBlacksInRange(i, n - 1);
    
    if (!visLeft[i][b]) {
        visLeft[i][b] = true;

        if (S[i] == '_') {
            memoLeft[i][b] = solLeft(i + 1, b);
        } else if (S[i] == 'X') {
            memoLeft[i][b] = canPlace(i, b) && solLeft(i + C[b] + 1, b + 1);
        } else {
            memoLeft[i][b] = (solLeft(i + 1, b)) || (canPlace(i, b) && solLeft(i + C[b] + 1, b + 1));
        }
    }
    return memoLeft[i][b];
}

bool solRight(int i, int b) {
    if (i < 0) 
        return b == -1;

    if (b == -1)
        return noBlacksInRange(0, i);
    
    if (!visRight[i][b]) {
        visRight[i][b] = true;

        if (S[i] == '_') {
            memoRight[i][b] = solRight(i - 1, b);
        } else if (S[i] == 'X') {
            memoRight[i][b] = canPlace(i - C[b] + 1, b) && solRight(i - C[b] - 1, b - 1);
        } else {
            memoRight[i][b] = (solRight(i - 1, b)) || (canPlace(i - C[b] + 1, b) && solRight(i - C[b] - 1, b - 1));
        }
    }
    return memoRight[i][b];
}

bool solutionWithBlock(int i, int b) {
    if (!canPlace(i, b))
        return false;
    
    return (solRight(i - 2, b - 1) && solLeft(i + C[b] + 1, b + 1));
}

void fillPossiblePositionsForBlocks() {
    for (int b = 0; b < k; b++) {
        for (int i = 0; i < n; i++) {
            if (solutionWithBlock(i, b)) {
                for (int j = 0; j < C[b]; j++) {
                    possible[i + j][b] = true;
                }
            }
        }
    }
}

bool canBeWhite(int i) {
    if (S[i] == 'X')
        return false;

    for (int b = -1; b < k; b++) {
        if (solRight(i - 1, b) && solLeft(i + 1, b + 1))
            return true;
    }

    return false;
}

bool canBeBlack(int i) {
    if (S[i] == '_')
        return false;

    for (int b = 0; b < k; b++) {
        if (possible[i][b])
            return true;
    }
    return false;
}

std::string solve_puzzle(std::string s, std::vector<int> c) {
    n = s.size();
    k = c.size();
    S = s;
    C = c;

    W[0] = S[0] == '_' ? 1 : 0;
    B[0] = S[0] == 'X' ? 1 : 0;
    for (int i = 1; i < n; i++) {
        W[i] = W[i - 1];
        W[i] += S[i] == '_' ? 1 : 0;
        B[i] = B[i - 1];
        B[i] += S[i] == 'X' ? 1 : 0;
    }

    fillPossiblePositionsForBlocks();
    /*for (int i = 0; i < n; i++) {
        for (int b = 0; b < k; b++) {
            std::cout << possible[i][b] << " ";
        }
        std::cout << "\n";
    }*/

    // ans
    std::string ans = s;

    for (int i = 0; i < n; i++) {
        if (!canBeWhite(i)) {
            ans[i] = 'X';
            continue;
        } 

        if (canBeBlack(i)) {
            ans[i] = '?';
        } else {
            ans[i] = '_';
        }
    }

    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...