This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "paint.h"
#include <bits/stdc++.h>
using namespace std;
const int mxn = 2e5+5;
const int mxk = 105;
/*
1. Craft a pseudo function that returns a boolean vector for each x "block"
times each position. [b][i] - true if it's possible to place first b+1 blocks
and the b-th one ending at i-th position
2. Run this function once
3. Reverse inputs
4. Run this function again and reverse it's results
5. If both endpoints of a block at some position are true then some valid
covering uses that block there. (Finding possible X characters done)
6. To find optional X places try "skipping" them, i.e. going form b to b+1
blocks where b-th ends before them and b+1-th starts after them.
*/
int n, k;
bool can_X[mxn], can_skip[mxn];
int pref[mxn];
vector<vector<bool>> calc(string s, vector<int> C) {
vector<vector<bool>> dp(k, vector<bool>(n));
for(int b = 0; b < k; b++) {
bool last_reachable = b == 0;
for(int i = C[b]-1; i < n; i++) {
if(i >= C[b] && s[i-C[b]] == 'X') {
last_reachable = false;
}
if(i >= C[b]+1 && s[i-C[b]] != 'X' && (b > 0 && dp[b-1][i-C[b]-1])) {
last_reachable = true;
}
// forgot optimizing with prefix sums
if(last_reachable && pref[i]-(i-C[b] < 0 ? 0 : pref[i-C[b]]) == 0) {
dp[b][i] = true;
}
}
}
return dp;
}
string solve_puzzle(string s, vector<int> C) {
n = s.size();
k = C.size();
pref[0] = s[0] == '_';
for(int i = 1; i < n; i++) {
pref[i] = pref[i-1]+(s[i] == '_');
}
auto dpL = calc(s, C);
reverse(s.begin(), s.end());
reverse(C.begin(), C.end());
pref[0] = s[0] == '_';
for(int i = 1; i < n; i++) {
pref[i] = pref[i-1]+(s[i] == '_');
}
auto dpR = calc(s, C);
reverse(s.begin(), s.end());
reverse(C.begin(), C.end());
for(int b = 0; b < k; b++) {
reverse(dpR[b].begin(), dpR[b].end());
}
reverse(dpR.begin(), dpR.end());
// all possible blocks
for(int b = 0; b < k; b++) {
for(int i = C[b]-1, rm = 0; i < n; i++) {
if(dpL[b][i] && dpR[b][i-C[b]+1]) {
for(int j = max(rm, i-C[b]+1); j <= i; j++) {
can_X[j] = true;
}
rm = i;
}
}
}
// all possible skipped positions
// don't forget skipping rightmost positions
// this is O(nk) ... probably
for(int b = 0, rm_done = 0; b < k; b++) {
int from = b == 0 ? 0 : n+1;
for(int i = C[b]-1; i < n; i++) {
if(i >= C[b] && s[i-C[b]] == 'X') {
from = n+1;
}
if(i >= C[b]+1 && s[i-C[b]] != 'X'
&& (b > 0 && dpL[b-1][i-C[b]-1] && dpR[b-1][i-C[b]-C[b-1]])) {
from = min(from, i-C[b]);
}
if(dpL[b][i] && dpR[b][i-C[b]+1]) {
for(; from <= i-C[b]; from++) {
can_skip[from] = true;
}
if(!rm_done && b == k-1) {
for(int j = i+1; j < n; j++) {
can_skip[j] = true;
}
rm_done = true;
}
}
}
}
string ans(n, '9');
for(int i = 0; i < n; i++) {
if(!can_X[i]) {
ans[i] = '_';
}
else if(!can_skip[i]) {
ans[i] = 'X';
}
else {
ans[i] = '?';
}
}
return ans;
}
/*
.X.X._.X_..
2 3 2
..X.._.X_..
2 3 2
sample:
..........
2
3 4
........
2
3 4
..._._....
1
3
.X........
1
3
*/
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |