문제 링크
- http://icpc.me/17823
사용 알고리즘
- Aliens Trick
- Parallel Binary Search
시간복잡도
- $O(N \log N \log X)$
풀이
구간의 양끝 원소의 사용 여부를 고정합시다. 각 구간의 양끝 원소의 사용 여부는 0부터 3까지의 정수로 인코딩할 수 있습니다. 또한, 구간의 양끝 사용 여부를 고정한 뒤 그래프를 잘 모델링하면 MCMF로 각 쿼리를 해결할 수 있습니다.
“구간 $[l, r]$의 양끝 사용 여부가 $bit$일 때 $k$개의 부분 수열의 합의 최댓값”을 $f(l, r, bit, k)$로 정의하면, MCMF로 문제를 해결할 수 있기 때문에 $f(l,r,bit,k)-f(l,r,bit,k-1) \geq f(l,r,bit,k+1)-f(l,r,bit,k)$가 성립해서 Aliens Trick을 적용할 수 있다는 것을 알 수 있습니다.
쿼리가 여러 개 주어지기 때문에 Parallel Binary Search를 생각해봅시다. PBS에서 우리가 수행해야 하는 연산은, “부분 수열 하나를 사용할 때 추가되는 비용이 $C$일 때 최적값”을 구하는 연산입니다.
각 정점에서 구간 $[l, r]$의 $f(l, r, bit, 1), f(l, r, bit, 2), \cdots , f(l, r, bit, r-l+1)$을 관리하는 세그먼트 트리를 만듭시다. 만약 이러한 세그먼트 트리를 전처리했다면, PBS의 각 결정 문제는 쿼리로 주어진 구간을 나타내는 $O(\log N)$개의 정점에 저장된 함수들을 보며 해결할 수 있습니다.
이 세그먼트 트리는 $O(N \log N)$에 만들 수 있습니다. 두 구간 $[l, m], [m+1, r]$을 합치는 것이 병목이 될텐데, 이 부분은 두 볼록 함수의 민코프스키 합($R_{i+j} = \max(A_i + B_j)$)를 계산하는 것이기 때문에 선형 시간에 합칠 수 있습니다. 그러므로 세그먼트 트리를 전처리하는 시간 복잡도는 $T(N) = 2T(N/2) + O(N) = O(N \log N)$이 됩니다. 다만, $m$과 $m+1$을 모두 사용하는 경우에는 두 구간을 concat해주면 사용하는 부분 수열의 개수가 한 개 감소하기 때문에 배열을 왼쪽으로 한 칸 shift 해야합니다.
이제 PBS를 합시다. 구간 개수 $k$와 추가 비용 $C$에 대해, $kC + f(k)$ 꼴의 최댓값을 계산하는 작업을 수행해야 하고, 이는 Convex Hull Trick과 매우 유사합니다. 심지어 세그먼트 트리의 각 정점에는 이미 볼록 함수가 저장되어 있기 때문에, 그냥 쿼리에 달려있는 $C$를 다 모아서 정렬한 뒤 선형 CHT 느낌으로 계산하면 됩니다.
PBS의 각 iteration마다 $O(N \log N)$ 시간이 걸리므로 전체 시간 복잡도는 $O(N \log N \log X)$가 됩니다. 물론, 다양한 bit의 조합을 계산해야 하기 때문에 세그먼트 트리를 전처리하는 과정과 PBS의 iteration에서 상수가 8 정도 더 붙습니다.
전체 코드
1 |
|