이 문제는 2단계로 생각해야 하는 문제다.
편의를 위해 범위의 연속된 전구를 끄는 행위를 라고 부르도록 하자.
당연히, 같은 범위의 전구를 2번 뒤집는 건 의미가 없다.
켜졌다 꺼질 것이라면 애초에 안 켜면 되니까...
따라서 최적의 경우, 특정 에 대해 는 1번 하거나, 0번 할 것이다.
예제 입력이 아래와 같이 인 경우를 보자.
7 3
1 0 1 0 1 0 1
번째 전구가 켜져있으므로 꺼야 하는데, 밖에는 끌 방법이 없다.
고로 을 무조건 1번 하게 되어있다.
그런데, 그렇게 하면 번째 전구가 켜진다.
이걸 끄려면? 이번에도 밖에는 끌 방법이 없다.
왜냐하면 이미 은 1번 해버려서, 한 번 더 하는 것은 의미가 없기 때문이다.
즉, 전구 배열을 까지 순회하면서,
번 전구가 켜져있으면 그리디하게 하는 풀이가 가능하다.
그런데 상식적으로 생각해봤을때, 한번 하려면 K개의 전구를 꺼야하니 가 걸린다.
그런데 만일 모든 범위를 해야하는 입력이 주어지면? 로 시간 초과다.
그러면 를 어떻게든 최적화해야 한다는건데... 이게 가능할까?
왜 이렇게 오래 걸리는지를 곰곰히 생각해보자.
번째 전구의 입장이 돼서 생각해보면, 모든 범위를 해야하는 입력의 경우
위처럼 총 개의 호출마다 꺼졌다 켜졌다, flip되기를 반복할 것이다.
번째 전구를 상수 횟수만 flip되도록 하는 방법이 없을까?
큐를 이용해, 딱 2번으로 제한하는 방법이 있다.
매 반복마다 뒤에 있는 개의 전구를 매번 끄는 대신에, 번에 끈다면, 까지 flip되었다는 상태를 큐에 저장하자.
번째 반복에선 우선 큐에서 번 이전 idx를 전부 pop()
해 지나간 반전을 무효화하고,
큐에 들어있는 원소의 개수가 짝수이면 flip의 flip이므로 현재 상태 그대로,
홀수이면 flip이므로 현재 상태를 반전시킨 다음 끌지 말지를 판단하자.
이러면 번째 원소는 최대 번 반전되므로, 만에 해결 가능하다.
꽤나 까다로운 문제였다. 푸는데 40분 걸렸다...
사실 소스에 주석으로 아이디어를 전부 적느라 시간이 오래 걸리긴 했다만.