[AtCoder] F - More Holidays
Incorrect solution: greedily find out how many consecutive S we can convert to all o. Then for the remaining replace operations, try each starting position in S.
Counter example: S = xooox, M = 2, K = 2. The incorrect solution will get oooooxooox, then run out of replacements, so it outputs 5. The correct answer is xoooooooox with length 8.
Correct solution:
1. the answer must start from an index in [0, N - 1]. If not, say if we start with index i > N - 1, then we can always achieve the same by starting with index i - N.
2. for each possible starting index i in [0, N - 1], binary search on the length of the longest consecutive o starting from index i:
- Search range: [0, N * M - start]
- given start index i and a total length, find out the number of replacements needed to achieve this length
- shrink the search range by half depending on the above check
3. take the max from step 2.
static void solve(int testCnt) {
for (int testNumber = 0; testNumber < testCnt; testNumber++) {
int n = in.nextInt();
long m = in.nextLong();
long k = in.nextLong();
char[] s = in.next().toCharArray();
int[] ps = new int[n];
ps[0] = s[0] == 'x' ? 1: 0;
for(int i = 1; i < n; i++) {
ps[i] = ps[i - 1];
if(s[i] == 'x') {
ps[i]++;
}
}
long ans = 0;
for(int start = 0; start < n; start++) {
ans = max(ans, compute(start, n, m, k, ps));
}
out.println(ans);
}
out.close();
}
static long compute(int start, int n, long m, long k, int[] ps) {
long l = 0, r = m * n - start;
while(l < r - 1) {
long mid = l + (r - l) / 2;
boolean f = helper(start, n, k, ps, mid);
if(f) {
l = mid;
}
else {
r = mid - 1;
}
}
return helper(start, n, k, ps, r) ? r : l;
}
static boolean helper(int start, int n, long k, int[] ps, long len) {
if(len <= n - start) {
int end = (int)(start + len - 1);
if(ps[end] - (start > 0 ? ps[start - 1] : 0) <= k) {
return true;
}
else {
return false;
}
}
else {
long whole = (len - (n - start)) / n;
long cost = whole * ps[n - 1] + ps[n - 1] - (start > 0 ? ps[start - 1] : 0);
int end = (int)((len - whole * n - (n - start)) - 1);
cost += end >= 0 ? ps[end] : 0;
if(cost <= k) {
return true;
}
else {
return false;
}
}
}