본문 바로가기
Problem Solving/Codeforces

Codeforces Round #321 (Div. 2)

by hongjun7 2015. 9. 27.

Contest Problems / Contest Standing

A. Kefa and First Steps

n개의 숫자가 주어졌을 때, maximum non-decreasing subsegment를 찾는 게 문제이다.

어떤 수열의 subsegment는 연속한 부분수열을 의미한다. 차례대로 수열의 원소들을 보면서, 새 원소가 이전의 원소보다 더 크다면 이전 원소의 maximum non-decreasing subsegment에 1을 더하여 답에 갱신하고, 아니면 현재의 maximum non-decreasing subsegment을 길이 1로 만들어 계속 진행해 나가는 방법으로 풀린다. O(n)에 풀 수 있다.


B. Kefa and Company

n명의 사람이 있는데, 각 사람마다 가진 money와 friendship이 주어진다. 주인공 Kefa는 몇 명의 무리를 정하려하는데, 임의의 무리 구성원 A, B에 대해서 A가 B보다 d 이상의 money를 가졌다면 B가 우울해한다. 이 때, 우울해하는 사람이 없도록 무리를 정해서 그 구성원들의 friendship의 합을 최대화하는 것이 문제이다.

사람들을 money순으로 정렬해놓고 보면, i번째 사람이 가장 적은 money를 가진 무리의 구성원일 때, 가장 큰 돈을 가진 구성원 B의 구간을 선형에 알 수 있고, 이 구간 안의 사람들은 모두 우울해하지 않는다는 성질을 알 수 있다. 따라서 이 구간을 모든 구간의 작은 index마다 이분탐색으로 찾을 수도 있고 - O(n log n), Loop Invariant를 이용해 구간의 양끝을 이동시켜보면서 모든 가능한 최대 구간을 선형 시간 내에 찾아볼 수 있다 - O(n). 아래의 내 코드는 후자의 방법을 이용하였다.


C. Kefa and Park

공원은 n개의 정점을 가지고 1번 정점이 루트인 모양의 트리이다. 각 정점에 고양이가 살고있는지 여부가 주어진다. 이 때, 트리의 말단 노드들에 대해서, 1번 정점에서부터 그 말단 노드 정점에 이르는 트리 상의 경로 중, m개보다 많은 연속한 노드들에 고양이가 산다면, 우리는 그 정점을 방문하지 못하는 정점이라고 부른다. 방문할 수 있는 정점의 수를 구하는 것이 문제이다.

DFS나 BFS로 트리를 구성하고, 말단 정점에서부터 올라오면서 연속한 고양이의 수 정보를 갱신하면서 m+1 이상이 된다면 그 경로를 invailid하다고 처리하면 된다. 최종적으로 루트 노드에까지 이르는 valid한 경로의 개수를 counting해서 출력하면 된다.


D. Kefa and Dishes

n개의 요리가 있고, 주인공은 m개의 요리만 먹는다.(n≥m) 각 요리마다 만족도가 주어진다. 그리고 어떤 요리를 먹은 후에 특정 요리를 먹으면 만족도가 더해지는 관계가 주어질 때, 최적으로 m개의 요리를 순서에 맞게 잘 먹어서 만족도를 최대화하는 것이 문제이다.

Bitmask Dynamic Programming으로 해결할 수 있다.

"D( status , last dish ) : 현재 먹은 요리의 상태를 2진수로 표현하였을 때의 값이 status이고 마지막으로 먹은 요리의 index가 last dish일 때의 만족도의 최댓값."


E. Kefa and Watch

0부터 9까지의 1자리 숫자로 구성된 n자리의 string이 있다. 여기에 2가지 연산을 각각 m번, k번 수행한다.

1) index L부터 index R까지의 string의 구성 성분을 모두 c( 0 ≤ c ≤ 9 )으로 바꾼다.

2) index L부터 index R까지의 string이 주기 d를 가지는지 그 여부를 출력한다. 주기가 d라면, string S가 index 1부터 N까지의 string에 대해서 모든 i에 대해 S( i ) = S( i + d - 1) ( 1 ≤ i ≤ N-d+1 )를 만족해야한다.

hash값을 가지고 Segment Tree혹은 Merge Tree를 구성하여 문제를 해결할 수 있다. 전처리로 길이가 M인 string의 모든 숫자가 k( 0 ≤ k ≤ 9 )일 때의 hash값을 구한 다음에 1)에 대해서 자릿수에 해당하는 값을 곱하여 O(log n)에 해결할 수 있다. 2)는 S(L ~ R-d)의 hash값과 S(L+d ~ R)의 hash값이 같은 지를 O(log n)에 판별하여 해결할 수 있다. hash값을 합하는 것은 길이와 값을 알면 O(1)에 계산할 수 있으므로 그 과정은 생략한다. 따라서 전체적으로 O( (m+k) log n )에 문제를 해결할 수 있게 된다.



'Problem Solving > Codeforces' 카테고리의 다른 글

Codeforces Round #125 (Div. 1)  (0) 2016.01.26
Codeforces Round #290 (Div. 2)  (0) 2016.01.24
Codeforces Round #292 (Div. 1)  (0) 2016.01.10
Codeforces Round #323  (0) 2015.10.05
Codeforces Round #322 (Div. 2)  (0) 2015.09.28

댓글