문제 링크
https://www.acmicpc.net/problem/19651
풀이
$[l, r]$ 사이의 수열이 등차수열이기 위해서는 $i \in [l,r-1]$ 인 $i$에 대해 $A_{i+1}-A_i$ 가 모두 같아야 합니다. 그렇다면 $A_i$를 관리하는 대신 $A_{i+1}-A_i$를 관리하고 이 값으로 2번 쿼리 $[i,j]$에서 값이 모두 동일한 가장 긴 연속 부분 수열의 길이를 빠르게 구하는 방법을 찾아야 합니다.
구간에서 값이 모두 동일한 가장 긴 연속 부분 수열의 길이는 금광 세그라고 불리는 테크닉을 이용해 $O(logN) $만에 구할 수 있습니다.
$A_{i+1}-A_i$를 세그먼트 트리로 관리하기로 했기 때문에 1번 쿼리로 변화하는 값들을 세그먼트 트리에서 업데이트하는 방법을 찾아야 합니다. 1번 쿼리 $[i, j]$가 주어졌을 때 $A_i - A_{i-1}$은 $x$만큼 증가하고 $A_{j+1}-A_j$는 $x + y ⋅ (j-i)$만큼 감소하고 $k \in [i,j-1]$ 인 k에 대해 $A_{k+1}-A_k$는 $y$만큼 증가합니다. 3개의 구간에 각각 동일한 값을 더 해주므로 이 값들을 lazy propagation으로 전파해 줄 수 있습니다. lazy propagation을 이용한 업데이트는 $O(\log N)$을 보장해 주기 때문에 1번 쿼리, 2번 쿼리 모두 $O(\log N)$만에 구할 수 있으므로 전체 시간복잡도는 $O(Q \log N)$입니다.
전체 코드
1 |
|
여담
의외로 수열과 쿼리 시리즈 중에 금광 세그테크닉을 이용해 값이 모두 동일한 가장 긴 연속 부분 수열의 길이를 구하는 문제가 없길래 템플릿에 도움이 될 겸 수열과 쿼리로 문제를 만들었습니다. lazy propagation을 이용하지 않는 풀이도 존재하니 궁금하면 JusticeHui 블로그의 백준19651 수열과 쿼리 39를 참고하는 것을 추천합니다.