Binary Search를 사용하는 문제입니다.
삭제된 1의 개수와 남아있는 0의 개수 중 큰 값의 최소값을 찾아야됩니다.
삭제하는 1의 개수를 binary search로 찾아야됩니다.
1을 삭제하면, 뒤에 있는 0들도 같이 지우는 것이 이득입니다. 그래서 1을 하나 지울 때 지워지는 0의 개수들을 저장해둡니다. 앞과 뒤 양방향에서 지울 수 있으므로 배열 2개를 이용해서 지워지는 0의 개수들을 저장해둡니다.
이제 binary search로 삭제하는 1의 개수를 찾습니다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
Integer t = Integer.parseInt(sc.nextLine());
while (t-- > 0) {
List<Integer> input = Arrays.stream(sc.nextLine().split("")).map(str -> Integer.parseInt(str))
.collect(Collectors.toList());
int n = input.size();
long numOnes = input.stream().reduce((x, y) -> x + y).get();
long numZeros = n - numOnes;
// save the number of removed zeros when remove i number of one from begin
List<Long> removedZerosFromFirst = new ArrayList<>();
// save the number of removed zeros when remove i number of one from end
List<Long> removedZerosFromLast = new ArrayList<>();
long cnt = 0;
for (int i = 0; i < n; i++) {
if (input.get(i) == 0) {
cnt++;
} else {
removedZerosFromFirst.add(cnt);
}
}
removedZerosFromFirst.add(cnt);
cnt = 0;
for (int i = n - 1; i >= 0; i--) {
if (input.get(i) == 0) {
cnt++;
} else {
removedZerosFromLast.add(cnt);
}
}
removedZerosFromLast.add(cnt);
long l = 0;
long r = numOnes;
long ans = 0;
while (l <= r) {
long mid = (l + r) / 2;
boolean isPossible = false;
for (int i = 0; i <= mid; i++) {
long leftZeros = numZeros;
leftZeros -= removedZerosFromFirst.get(i);
leftZeros -= removedZerosFromLast.get((int) mid - i);
if (leftZeros <= mid) {
isPossible = true;
break;
}
}
if (isPossible) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
System.out.println(ans);
}
sc.close();
}
}
반응형
'codeforce' 카테고리의 다른 글
C. Rooks Defenders - Codeforces Round #791 (Div. 2) (0) | 2022.05.18 |
---|