ICPC WF 연습 (2/3)

장난감 경주

부등식을 가지고 노는 문제이다.

브론즈 문제인데 10분 넘게 걸렸다. 왜인지는 잘 모르겠다... 13분 AC.

The Shortest Period

길이 NN인 문자열 SS에서 하나의 문자를 지웠을 때 얻어지는 문자열의 주기의 최솟값을 구하는 문제이다.

문자열 S[1⋯N]S[1 \cdots N]의 주기가 dd라는 것은, S[1⋯N−d]=S[d+1⋯N]S[1 \cdots N-d] = S[d+1 \cdots N]과 동치이다.

이제, 원래 문제로 돌아가서, SS에서 하나의 문자를 지워서, 길이 LL의 Prefix와 Suffix가 서로 같도록 만들 수 있는지 판별해보자. 다음 네 가지 경우를 고려하면 된다: (xx번째 문자를 지운다고 하자.)

  1. S[1⋯L]=S[N−L+1⋅N]S[1 \cdots L] = S[N-L+1 \cdot N] (L<x<N−L+1)(L < x < N-L+1)
  2. S[1⋯L]=S[N−L⋯N]S[1 \cdots L] = S[N-L \cdots N] (max⁡(L+1,N−L)≤x≤N)(\max(L+1, N-L) \le x \le N)
  3. S[1⋯L+1]=S[N−L+1⋯N]S[1 \cdots L+1] = S[N-L+1 \cdots N] (1≤x≤min⁡(L+1,N−L))(1 \le x \le \min(L+1, N-L))
  4. S[1⋯L+1]=S[N−L⋯N]S[1 \cdots L+1] = S[N-L \cdots N] (N−L≤x≤L+1)(N-L \le x \le L+1)

먼저, 부분문자열의 동일 여부 판별은 Hashing을 이용하자. O(N2)O(N^2)번의 비교가 이루어지므로, 10910^9-scale의 소수 두 개를 이용해야 안전하다.

Case 1은 아주 쉽다. Case 2, 3도 적당한 이분 탐색으로 xx를 찾을 수 있다.

Case 4가 이 문제에서 가장 어려운 부분이다. Case 2, 3과 동일한 아이디어를 이용하면, xx로 가능한 Indices의 범위가 나온다. 이제, 적당히 문제를 변형하면, 다음과 같이 문제가 환원된다:

NN개의 공이 일렬로 배열되어 있다. 각 공의 색은 빨강 혹은 파랑이다. 함수 ff를 적절히 호출하여, 연속한 KK개의 빨간 공이 존재하는지 판별하시오.

함수 f(s,e)f(s, e)는 ss번째 공부터 ee번째 공까지 모두 빨간 공인지 여부를 반환한다.

이 문제는 함수 ff를 O(NKlg⁡K)O\left( \frac{N}{K} \lg K \right)번만 호출해서 해결할 수 있다. NN개의 공을 KK개씩 끊어 O(NK)O\left( \frac{N}{K} \right)개의 버킷을 만든 후, 각 버킷에 대해 "왼쪽부터 연속한 빨간 공의 개수"와 "오른쪽부터 연속한 빨간 공의 개수"를 이분 탐색으로 세어주면 된다.

환원된 문제의 아이디어를 잘 적용하면, Case 4를 O(NLlg⁡L)O\left( \frac{N}{L} \lg L \right)에 처리할 수 있다.

따라서, 전체 문제를 O(∑LNLlg⁡L)=O(Nlg⁡2N)O\left( \sum_{L} \frac{N}{L} \lg L \right) = O\left( N \lg^2 N \right)에 해결할 수 있다. 2시간 AC.

dotorya는 Suffix Array를 이용해서 풀었다. 어떻게...?

Termites

NN개의 수 A1⋯ANA_1 \cdots A_N가 있다. 두 명이 서로 번갈아가면서, 00과 이웃한 수 Ai≠0A_i \ne 0를 골라, 자신의 점수에 더한 후, AiA_i의 값을 00으로 바꾼다. 각자 최선을 다할 때, 최종 점수를 구하는 문제이다.

여러 생각을 해봤는데, O(N2)O(N^2)에도 못 풀겠다. 대충 찾아보니, 논문이 나온다.

세상에... 논문에서 "Fusion Principle" 이름만 보자마자 풀이를 알아버렸다. 알고 있는 테그닉인데 떠올리지 못한 점이 아쉽다.

NN개의 수가 있고, 서로 번갈아가면서 좌우의 수를 하나씩 뽑는 (단순한 버전의) 문제를 생각하자. 인접한 세 수 aa, bb, cc에 대하여, b=max⁡(a,b,c)b = \max (a, b, c)라면, 이 세 수를 하나의 수 a+c−ba + c - b로 합칠 수 있다. 만일, 상대방이 aa를 가져간다면, 나는 즉시 bb를 가져가고, 상대방은 남은 cc까지 가져가는 전략이 항상 최적이기 때문이다.

이러한 Reduction을 계속 진행하면, 남은 수는 정렬되어있다. 이제, 가장 큰 수부터 차례대로 나누어 가지면, 그것이 답이 된다.

원 문제에서는 한 쪽 끝이 막혀있을 수 있는데, 비슷하게 적당히 처리하면 된다. 전체 시간 복잡도는 O(Nlg⁡N)O(N \lg N).

Termites 2

트리에서 논다...

Tighten Up!

이차원 평면에 NN개의 못이 박혀 있고, NN-lines chain 형태의 실이 있다. 실의 양쪽 끝을 평면에 수직한 방향으로 잡아당겨, 실이 못에 적당히 걸쳐 팽팽해지도록 한다. 이때, 실의 길이를 구하는 문제이다.

재미있는 기하 문제이다. 실의 상태를 못에 대한 상대적인 위치를 이용하여 나타내면 해결할 수 있다.