거짓말쟁이 구간을 [L,R]이라 하자. i번 사람이 거짓말쟁이라는 조건은 i∈[L,R]이고, i번 사람의 주장이 참이라는 조건은 [li,ri]가 [L,R]과 교차하는 것이다. 두 조건의 참과 거짓은 서로 반대여야 한다.
각 사람에 대해 다음 네 값을 정의한다.
ai=min(i,ri),bi=max(i,li),ci=min(i,li),di=max(i,ri).
i번 사람이 구간 안에 있으면서 주장이 참인 경우는 정확히 L≤ai이고 bi≤R인 경우이다.
i번 사람이 구간 밖에 있으면서 주장도 거짓인 경우는 다음 세 형태 중 하나이다.
- R<ci.
- di<L.
- ai<L≤R<bi. 마지막 형태는 i와 주장 구간이 서로 떨어져 있을 때 그 사이에 거짓말쟁이 구간이 놓이는 경우이다.
따라서 다음 값을 정의한다.
A=imindi,B=imaxci,
M(L)=ai<Lmaxbi,G(L)=ai≥Lminbi.
M(L)의 집합이 비어 있으면 0, G(L)의 집합이 비어 있으면 N+1로 정의한다.
구간 [L,R]이 정답일 필요충분조건은 다음과 같다.
L≤A,max(B,L,M(L))≤R<G(L).
첫 번째 부등식은 모든 di<L 형태를 막는다. R≥B는 모든 R<ci 형태를 막는다. R≥M(L)는 ai<L≤R<bi 형태를 막는다. 마지막으로 R<G(L)는 L≤ai이고 bi≤R인 사람을 없앤다. 따라서 이 조건들은 위의 모든 모순을 정확히 제거한다.
이제 동적으로 M(L)과 G(L)을 다룬다. 각 좌표 x에 대해 다음 두 값을 유지한다.
hix=ai=xmaxbi,lox=ai=xminbi.
그러면 M(L)은 hi의 접두 최댓값이고, G(L)은 lo의 접미 최솟값이다. 같은 ai를 가진 여러 사람은 multiset으로 관리한다. A와 B도 각각 di와 ci의 multiset으로 관리한다.
좌표 1,2,⋯,N을 크기 약 N인 블록으로 나눈다. 블록 [s,e] 안의 각 후보 L에 대해 다음 값을 미리 계산한다.
XL=max(L,s≤x<Lmaxhix),YL=L≤x≤eminlox.
XL과 YL은 모두 L에 대해 감소하지 않는다. 또한 XL<YL인 위치들을 따로 저장한다.
현재 블록보다 앞의 hi 최댓값을 P, 뒤 블록들의 lo 최솟값을 S라 하자. 이 블록의 후보 L이 가능하려면
max(B,P,XL)<min(S,YL)
이어야 한다. 이는 다음 네 조건과 동치이다.
- max(B,P)<S.
- XL<S.
- YL>max(B,P).
- XL<YL.
XL,YL이 단조이므로 두 번의 이분 탐색으로 가능한 위치 범위를 구하고, 저장해 둔 XL<YL 위치가 그 범위에 있는지 확인할 수 있다. 찾았다면
R=max(B,P,XL)
로 두면 된다. L≤A인 후보만 조사한다.
한 번의 주장 변경은 기존 좌표 ai와 새로운 좌표 ai가 속한 블록만 바꾼다. 따라서 최대 두 블록을 다시 계산하면 된다.
각 변경의 시간 복잡도는 O(NlogN)이고, 전체 메모리 복잡도는 O(N)이다.
Solution written by GPT5.6