A번 - 선물

양말을 $2X$개 구매하기 위한 최소 비용을 구하는 문제입니다. 문제에 따르면 양말은 항상 연속된 이틀에 걸쳐서 사야하고, 매일 $X$개씩 구매하려고 해야 합니다.

$i$일에 양말을 $X$개 구매했다면, $i+1$일에도 양말을 $X$개 구매해야 합니다. 이때 양말을 구매하는 총 비용은 $A_i \times X + A_{ i+1 } \times X$ 입니다.

가능한 모든 $i$ ($1 \le i \le N-1$) 중에서 최소가 되는 $i$를 찾고, 그때 비용을 계산하면 됩니다.

소스 1

B번 - 운명

왼발에 신을 수 있는 양말이 $X$개 있고, 오른발에 신을 수 있는 양말도 $X$개 있습니다. 양말의 색은 $K$가지 존재합니다.

왼발 양말 하나와 오른발 양말 하나를 신고 나가려고 하는데, 두 양말의 색은 달라야 합니다. 이때 양말을 신을 수 있는 방법의 수를 구하는 문제입니다.

각각의 왼발에 신을 수 있는 양말마다 색이 다른 오른발 양말의 개수를 세어주는 방식으로 해결 할 수 있습니다.

소스 2

소스 2와 같이 구현하면 방법의 수를 구할 수 있습니다. 이 소스의 시간 복잡도는 $O(X^2)$ 입니다. 하지만, 문제의 $X$ 제한은 $X \le 100\,000$이기 때문에, 를 받게 됩니다.

색이 $u$인 왼쪽 양말의 개수를 $l$, 오른쪽 양말의 개수를 $r$이라고 합시다. 이때 색이 $u$인 왼쪽 양말을 하나 신었을때 신을 수 있는 오른쪽 양말의 개수는 $X - r$개 입니다. 색이 $j$인 오른쪽 양말의 개수를 미리 구해놓았다면, 양말을 하나씩 검사하지 않고도 개수를 구할 수 있게 됩니다.

소스 3은 이 아이디어를 이용해 구현한 소스입니다. cnt[j]에는 색이 j인 오른쪽 양말의 개수가 저장되어 있습니다.

소스 3

C번 - 해킹

$N$개의 컴퓨터와 $M$개의 통신망이 있고, $i$번 컴퓨터를 해킹하면 1분 뒤부터 매분 $A_i$의 돈을 가져올 수 있습니다. $X$개의 컴퓨터를 해킹해야 합니다.

$B_1 , B_2 , \dots , B_Y$번 컴퓨터에는 보안 시스템이 설치될 예정입니다. 이것이 설치된 컴퓨터에서는 돈을 가져올 수 없고, 설치되고 1분 뒤에는 통신망으로 직접 연결된 모든 컴퓨터에 보안 시스템이 자동으로 설치됩니다.

문제의 목표는 얼마나 많은 돈을 얻을 수 있을지 구하는 것입니다.

많은 돈을 얻으려면 해킹한 컴퓨터에 보안 시스템이 최대한 늦게 설치되어야 합니다. 이를 위해 각 컴퓨터에 언제 보안 시스템이 설치되는지 구해야합니다. 컴퓨터와 통신망은 그래프로 모델링할 수 있습니다. 한 컴퓨터에 보안 시스템이 설치되고, 직접 연결된 다른 컴퓨터에 보안 시스템이 설치되는데는 1분이 걸립니다. 이것은 간선의 가중치가 $1$인 것으로 볼 수 있습니다. 따라서, 한 컴퓨터에 보안 시스템이 설치되는 시간은 BFS 알고리즘으로 구할 수 있습니다.

BFS 알고리즘을 이용해 각 컴퓨터에 보안 시스템이 설치되는 시간을 구합니다. $i$번 컴퓨터에 보안 시스템이 설치되는 시간을 $T_i$라고 합시다. 그럼 이 컴퓨터에서 얻을 수 있는 돈의 양은 $T_i \times A_i$ 입니다. 여기서 가장 큰 $X$개의 합이 문제의 정답이 됩니다.

만약, 그래프가 연결되어 있지 않다면, 보안 시스템이 설치되지 않는 컴퓨터가 존재합니다. 이 경우 무한히 많은 돈을 얻을 수 있습니다. 하지만, 보안 시스템이 설치되지 않은 컴퓨터가 있다고 하더라도 항상 돈을 무한히 얻을 수 있는 것은 아닙니다. 문제의 $A_i$ 조건은 $0 \le A_i \le 500\,000$이기 때문에, $A_i$가 $0$인 경우가 존재할 수 있습니다. 보안 시스템이 설치되지 않은 컴퓨터에서 매분 $0$만큼의 돈을 가져올 수 있다면, 무한히 많은 돈을 얻는 경우는 아닙니다.

소스 4

D번 - 스터디 카페

$i$일에 $k$명이 방문했을때 그 날 얻을 수 있는 수익의 최댓값은 $A_i$에서 가장 큰 값 $k$개입니다. 최솟값도 비슷한 방식으로 구할 수 있습니다.

$i$일에 방문한 사람의 수가 $V_i$명이라면, 위의 방법을 이용해서 문제의 정답을 구할 수 있습니다. 이렇게 해결하려면 크기가 $10^9$인 배열이 필요합니다. 그 다음, 각각의 사람 $j$마다 $S_j$부터 $E_j$까지 순회하면서 $V$의 값을 $1$ 증가시켜야 합니다. 공간도 너무 많이 필요하고, 시간도 너무 많이 걸립니다. 다른 방법을 생각해봅시다.

스터디 카페에서 사람이 변하는 날짜는 최대 $2M$개가 있습니다. 사람이 변하지 않는 기간이 있다면, 이때 얻을 수 있는 수익은 한 번에 구할 수 있습니다. 예를 들어, $2$, $3$, $4$일에 사람이 $1$명 왔고, $5$일에 사람이 $2$명 왔다면, $2$, $3$, $4$에서 얻을 수 있는 수익의 최솟값과 최댓값은 변하지 않습니다. 이 아이디어를 이용해 사람이 변하지 않는 기간을 한 번에 처리할 수 있습니다.

$A_i$에서 가장 큰 값 $k$개의 합과 작은 값 $k$개의 합은 누적 합을 이용해 $O(1)$에 구할 수 있습니다.

소스 5

a_min은 입력으로 주어진 $A$가 오름차순으로, a_max는 내림차순으로 저장되어 있습니다. 이 값을 이용해 누적 합 pre_minpre_max를 구할 수 있습니다.

a에 들어가는 값은 timewhat입니다. time은 사람이 변하는 시점이고, what0이면 사람이 감소, 1이면 증가하는 것입니다. 어떤 사람이 스터디 카페를 u일부터 v일까지 이용했다면, 사람의 수가 변할 수 있는 시점은 u일과 v+1일이기 때문에, v1을 더해서 넣습니다.

cnt에는 스터디 카페에 있는 사람의 수, last에는 마지막으로 수익을 구한 날짜가 저장되어 있습니다.

이를 이용해 사람이 변하는 날마다 얻을 수 있는 수익을 한 번에 구할 수 있습니다.

E번 - 육각형 순회

문제에 설명에 나와있는 건축물을 크기가 $N$인 지도로 표현하겠습니다.

임의의 위치 $(x, y)$에 대한 정답을 구할 수 있다면, 나머지 위치에 대해서도 답을 항상 구할 수 있습니다. 그 이유는 모든 방을 정확히 한 번씩 돌아본 후 다시 원래의 위치로 돌아와야 하기 때문입니다.

$(1, 1)$은 모든 크기 $N$에 대해서 존재하는 위치이기 때문에, 각각의 크기 $N$마다 어떻게 방법을 구할 수 있는지 알아보겠습니다.

그림 1. $N = 5$

여기서 $(1, 1)$, $(2, 2)$, $\dots$, $(N, N)$까지 칸을 빨간색으로 색칠해봅시다.

그림 2

빨간색 칸을 제외한 칸 중에서 가장 외곽에 있는 칸을 파란색으로 색칠해봅시다.

그림 3

그 다음 외곽에 있는 칸은 초록색으로 색칠해봅시다.

그림 4

이런 식으로 외곽의 색을 모두 다르게 칠할 수 있습니다.

그림 5

$(1, 1)$에서 시작해서 각각의 외곽을 모두 방문하고, $(N, N)$에 방문한 다음, 여기서 빨간색 칸을 이용해서 $(1, 1)$로 돌아오는 경로를 모든 $N$에 대해서 만들 수 있습니다.

그림 6

소스 6

  • limits[r]: r번 행의 마지막 열 번호가 limits[r]
  • check[r][c]: (r, c)를 방문한 적이 있으면 true, 아니면 false
  • dc[k]: k번 방향을 나타내는 대문자
  • dx[k]: dc[k]번 방향으로 이동했을때 행의 변화
  • dy1[k], dy2[k]: dc[k]번 방향으로 이동했을때 열의 변화
    • 열의 변화는 n번 행을 기준으로 다르기 때문에 두 가지 사용
  • path: 방문한 칸을 순서대로 저장
  • direction: 방문한 방법을 순서대로 저장