Submission #999361

#TimeUsernameProblemLanguageResultExecution timeMemory
999361ByeWorldPaint By Numbers (IOI16_paint)C++14
100 / 100
180 ms209364 KiB
#include "paint.h" #include <bits/stdc++.h> #define ll long long #define pb push_back #define fi first #define se second using namespace std; const int MAXN = 2e5+5; const int MAXK = 105; const int INF = 1e9+10; typedef pair<int,int> pii; /* idea: dpP[i][j] = can 's[i]' be black if you only consider the first 'j' segments ans it is the end of the 'j'th segment canP[i][j] = can the prefix i indexes be valid if you only consider the first 'j' segments dpS[i][j] = can 's[i]' be black if you only consider the last 'j, j+1... k' segments ans it is the start of the 'j'th segment canP[i][j] = can the idx 'i, i+1,...,n' be valid if you only consider the 'j, j+1, ..., k' segments to answer: check if idx 'i' can be black and/or white */ int n; string s, ANS; int cnt[MAXN]; int dpP[MAXN][MAXK], dpS[MAXN][MAXK], bl[MAXN], wh[MAXN]; bool canP[MAXN][MAXK], canS[MAXN][MAXK]; vector <int> c; int k; string solve_puzzle(string S, vector<int> C) { s = '_'+S+'_'; n = s.size()-2; for(int i=1; i<=n; i++) cnt[i] = cnt[i-1] + (s[i]=='_'); c.pb(-1); for(auto in : C) c.pb(in); k = c.size()-1; dpP[0][0] = 1; canP[0][0] = 1; for(int i=1; i<=n; i++){ for(int j=1; j<=k; j++){ int len = c[j]; // we want to put the segment on [i-c[j]+1, ..., i] if(i-c[j]+1 <= 0) continue; if(cnt[i]-cnt[i-c[j]] != 0) continue; // there is white if(s[i-c[j]] == 'X') continue; // can't make the segment if(i-c[j]==0){ // extreme case if(canP[i-c[j]][j-1]) dpP[i][j] = 1; } else if(canP[i-c[j]-1][j-1]){ // if j-1 segment is valid dpP[i][j] = 1; } } // build canP for(int j=0; j<=k; j++){ // a[i] becomes ending of segment j if(s[i] != 'X'){ // use last canP and this dpP canP[i][j] = canP[i-1][j] | dpP[i][j]; } else { // has to be X, so check dpP canP[i][j] = dpP[i][j]; } } } dpS[n+1][k+1] = 1; canS[n+1][k+1] = 1; for(int i=n; i>=1; i--){ for(int j=k; j>=1; j--){ // a[i] becomes start of segment j int len = c[j]; // we want to put segment on [i, ..., i+c[j]-1] if(i+c[j]-1 > n) continue; if(cnt[i+c[j]-1]-cnt[i-1] != 0) continue; if(s[i+c[j]] == 'X') continue; // can't if(i+c[j]==n+1){ // extreme case if(canS[i+c[j]][j+1]) dpS[i][j] = 1; } else if(canS[i+c[j]+1][j+1]){ dpS[i][j] = 1; } } // build canS for(int j=k+1; j>=1; j--){ if(s[i] != 'X'){ canS[i][j] = canS[i+1][j] | dpS[i][j]; } else { canS[i][j] = dpS[i][j]; } } } for(int i=1; i<=n-1; i++){ for(int j=1; j<=k; j++){ if(dpP[i][j] && canS[i+2][j+1] && s[i+1] != 'X'){ // if the prefix [1, ..., i] and suffix [i+2, ... , n] is valid bl[i-c[j]+1]++; bl[i+1]--; // prefix difference to update quickly } } } { int i=n; // extreme case if(dpP[i][k]){ bl[i-c[k]+1]++; bl[i+1]--; } } for(int i=1; i<=n; i++){ for(int j=0; j<=k; j++){ if(canP[i-1][j] && canS[i+1][j+1]){ // if [1, ..., i-1] and [i+1, ..., n] can put all segments wh[i] = 1; } } } for(int i=1; i<=n; i++) bl[i] += bl[i-1]; // prefix difference for(int i=1; i<=n; i++){ if(s[i] != '.'){ ANS += s[i]; continue; } if(bl[i] && wh[i]) ANS += '?'; else if(bl[i]) ANS += 'X'; else if(wh[i]) ANS += '_'; else assert(false); } return ANS; }

Compilation message (stderr)

paint.cpp: In function 'std::string solve_puzzle(std::string, std::vector<int>)':
paint.cpp:45:8: warning: unused variable 'len' [-Wunused-variable]
   45 |    int len = c[j];
      |        ^~~
paint.cpp:72:8: warning: unused variable 'len' [-Wunused-variable]
   72 |    int len = c[j];
      |        ^~~
#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...