IOI 2014 Holiday

2019. 8. 29. 23:48알고리즘 문풀/Others

문제 링크

 

10076번: 휴가

문제 지안지아는 타이완에서의 휴가를 계획하고 있다. 휴가동안 지안지아는 도시에서 도시로 이동하고 도시 안의 관광지들을 방문할 것이다. 타이완에는 하나의 고속도로를 따라서 개의 도시들이 위치한다. 이 도시들은 순서대로 0부터 n-1까지의 번호가 붙어있다. 임의의 i(0 < i < n-1)에 대해서, 도시 i의 인접한 도시는 도시 i-1과 i+1이다. 도시 0과 인접한 도시는 도시 1뿐이고, 도시 n-1과 인접한 도시는 도시 n-2뿐이다. 각 도시에는 여러

www.acmicpc.net

PS-hell 스터디에서 가장 먼저 해결한 문제다.

문제 내용

길이 \(n\)의 선형 배열 \(a[0\ldots n-1]\)가 있다.

\(s\)번째 entry에서 시작해서 한 턴에 다음의 동작들을 할 수 있다.

초기 점수가 0점이고 현재 위치가 \(i\)번 이라고 할 때,

  • Stay : 현재 점수에 \(a[i]\)를 더한다. 단, 한 번 Stay한 곳의 배열 값을 중복해서 더할 수 없다.
  • goLeft, goRight : 각각 \(i-1\)번, \(i+1\)번 entry로 이동한다.

총 \(d\)턴 동안 점수를 최대화하는 문제이다.

 


스포방지선

 

 

 

 

 

 

 

 

 

 

 


기본 관찰

Stay를 제외하면, 이동을 LL....LRR...R 또는 RR...RLL...L 형태로 하는 것이 최적임을 알 수 있다.

RR...RLL...L 형태는 배열을 뒤집어서 동일한 과정을 반복하는 것으로 고려할 수 있다.

 

따라서 탐색할 구간 \([l, r]\)을 고정하면 이동에 소모하는 턴(날짜) 수는 \(s - l + r - l\)턴이므로 총 \(g(l, r) = \min(r-l+1, d+2l-r-s)\)턴 동안 Stay를 할 수 있다.

 

따라서 \([l, r]\)에서 최대의 \(g(l, r)\)개 원소를 뽑아주면 된다. \(l\)을 고정하고 \(r\)을 늘려가면서 std::set 등으로 관리하면 \(O(N^2 \lg N)\)에 문제를 해결할 수 있다. \(l \le s \le r\)이 성립해야 한다.

 

DnC approach

시간복잡도를 줄이기 위해서는 모든 \([l, r]\)을 다 보면 안된다. 한 가지 중요한 관찰은 고정된 \(l\)에 대해서 답을 최대로 하는 \(r\)값을 \(f(l)\)이라고 하면, \(f(l)\)이 \(l\)에 따라 단조증가한다는 것이다.

 

따라서 다음의 pseudo-code가 잘 작동한다:

 

def solve(s, e, d, u): #[s, e] : candidates for l, [d, u] : candidates for r; i.e. f(m)
	if(s > e): return
    m = (s + e) // 2
    
    opt = f(m, d, u) #gets f(m) with an appropriate O(e-s + u-d) procedure
    
    solve(s, m-1, d, opt)
    solve(m+1, e, opt, u)

가능한 후보를 Segment Tree나 set 등의 자료구조로 잘 manage하면 \(f(l)\)을 \(\mathcal{O}(N\lg N)\)에 구할 수 있고, 전체 복잡도는 \(\mathcal{O}(N\lg^{2} N)\). 단, 분할 정복 과정에서 update가 \(\mathcal{O}(e-s + u-d)\)번 정도만 수행되도록 잘 유지해야 한다. 구현 자유도는 굉장히 높은 것 같다. 메모리가 64MiB라서 Persistent Segment Tree를 쓰려면 주의해야 하는...줄 알았지만 PST로 만점을 받은 사람도 많이 있는 것 같다.

 

나는 가장 큰 \(k\)개의 합이 지원되는 Segment Tree로 풀었다.

 

 

\(\mathcal{O}(N\lg N)\) sketch

\(f(l, r)\)을 \([l, r]\)에서 가장 큰 \(g(l, r)\)개 수의 합이라고 하자.

그렇다면 \(l_{1} < l_{2} \le r_{1} < r_{2}\)에 대해 \(f(l_{1}, r_{1}) < f(l_{1}, r_{2}) \implies f(l_{2}, r_{1}) < f(l_{2}, r_{2})\)가 성립한다. 이를 total monotonicity라고 한다.

 

\(R \times C\) Totally monotone matrix \(f[l, r]\)에 대해, row minima를 구하는 \(\mathcal{O}(R + C)\) 알고리즘이 알려져 있다. \(f(l, r)\)을 amortized \(O(\lg N)\) 정도에 구할 수 있으니, 아마 \(\mathcal{O}(N \lg N)\)에 문제를 풀 수 있을 것이다. 솔직히 구현이 귀찮아서 해보진 않았다.

'알고리즘 문풀 > Others' 카테고리의 다른 글

UCPC 2020 본선 후기  (0) 2020.08.01
ICPC Seoul Regional 2019 후기  (1) 2019.11.13
[PS 켠왕 #1] BOJ 10641 The J-th Number  (0) 2019.08.15
NYPC 2018 넋두리  (3) 2018.10.28
[추석맞이 폴란드 스터디] 180925  (0) 2018.09.26