온라인 vs 오프라인
온라인은 질의를 받는 즉시 답해야 하고, 이전 답이 다음 입력에 영향을 줄 수
있다. 오프라인은 모든 질의를 미리 받아 둘 수 있어, 유리한 순서로 재배열해
처리할 수 있다. 이 자유도가 오프라인 기법의 힘이다.
핵심 발상: "질의에 답하는 순서는 입력 순서와 같을 필요가 없다." 질의를 정렬
하거나 묶어 처리하면 자료 구조의 갱신 횟수를 극적으로 줄일 수 있다.
대표 패턴 1: 정렬 후 스위핑
질의와 원소를 같은 기준(보통 값이나 좌표)으로 정렬하고, 포인터를 전진시키며
"지금까지 조건을 만족하는 원소"만 자료 구조에 반영한 상태에서 답한다.
예: "각 질의 \((x_q)\)에 대해 값이 \(x_q\) 이하인 원소들 중 ...". 질의를 \(x_q\)
오름차순으로 정렬하고, 원소도 값 오름차순으로 보면서 포인터를 밀면, 각 원소는
정확히 한 번만 자료 구조에 삽입된다. 삽입 총 \(O(N \log N)\), 질의 총
\(O(Q \log N)\).
대표 패턴 2: 좌표·시간 차원 추가
2차원 직사각형 질의를 한 축으로 정렬해 1차원 문제 \(\times\) 스위프로 낮춘다.
"점 추가 / 직사각형 안 점 개수" 같은 문제가 전형적인데, 질의를 누적 합 형태로
쪼개(포함-배제) y축 BIT/세그 트리에 올린다.
대표 패턴 3: 차분으로 질의 분해
구간 질의 \([l, r]\)을 \(f(r) - f(l-1)\)로 쪼개면, 각 끝점을 독립된 "한쪽
질의"로 만들 수 있다. 이렇게 쪼갠 끝점들을 모아 정렬해 한 번의 스위프로 모두
처리한다.
왜 빠른가
온라인이라면 각 질의마다 자료 구조를 처음부터 세우거나 비싼 연산을 해야 할 수
있다. 오프라인은 상태를 단조롭게 키워 가며(원소를 한 번씩만 추가) 모든 질의를
한 번의 스위프로 답하므로, 갱신 비용이 질의 사이에 분할상환된다.
한계
- 답이 다음 질의에 영향을 주는 진짜 온라인 강제(예: XOR로 인덱스 인코딩)는
오프라인이 불가능하다. 이럴 땐 퍼시스턴트 자료 구조가 필요하다. - 질의를 모두 저장할 메모리가 있어야 한다.
오프라인은 그 자체로 알고리즘이라기보다 사고 틀이다. Mo's 알고리즘,
오프라인 동적 연결성, 병렬 이분 탐색이 모두 이 틀의 발전형이다.