[Baekjoon] 19951. 태상이의 훈련소 생활
19951. 태상이의 훈련소 생활
시간 제한 | 메모리 제한 |
---|---|
1초 | 512MB |
문제
2020년 5월 14일 논산훈련소에 입대한 태상이는 첫 총기 훈련에서 가스 조절기를 잃어버리는 중대한 실수를 범했다. 그로 인해, 태상이는 조교들에게 눈총을 받게 되었다. 조교들은 태상이에게 연병장(운동장)의 흙을 옮기는 일을 주고 제대로 수행하지 못하면 징계를 내리려고 한다.
연병장은 일렬로 이어진 N개의 칸으로 이루어져 있으며 각 칸마다 높이를 가지고 있고, 첫 번째 칸부터 순서대로 1번,2번,3번,...,N번 칸으로 명칭이 붙어있다. 조교들은 총 M명이 있으며, 각 조교들은 태상이에게 a번 칸부터 b번 칸까지 높이 k만큼 흙을 덮거나 파내라고 지시한다. 흙은 주변 산에서 얼마든지 구할 수 있으므로 절대로 부족하지 않다.
태상이는 각 조교의 지시를 각각 수행하면, 다른 조교의 지시로 흙을 덮어둔 칸을 다시 파내기도 하는 비효율적인 일이 발생하는 것을 깨달았다. 그래서 태상이는 각 조교의 지시를 모아 연병장 각 칸의 최종 높이를 미리 구해 한 번에 일을 수행하려고 한다.
불쌍한 태상이를 위해 조교들의 지시를 모두 수행한 뒤 연병장 각 칸의 높이를 구하자.
입력
첫 줄에 연병장의 크기 N과 조교의 수 M이 주어진다.
둘째 줄에 연병장 각 칸의 높이 Hi가 순서대로 N개 주어진다.
셋째 줄부터 M개의 줄에 각 조교의 지시가 주어진다.
각 조교의 지시는 세 개의 정수 a,b,k로 이루어져 있다.
- k>=0인 경우 a번 칸부터 b번 칸까지 높이가 각각 |k|만큼 늘어나도록 흙을 덮어야 한다.
- k<0인 경우 a번 칸부터 b번 칸까지 높이가 각각 |k|만큼 줄어들도록 흙을 파내야 한다.
출력
모든 지시를 수행한 뒤 연병장 각 칸의 높이를 공백을 사이에 두고 출력한다.
제한
- 1<=N<=100,000
- 1<=M<=100,000
- -10,000<=Hi<=10,000
- N,M,Hi는 정수
- 조교의 지시
- 1<=a<=b<=N
- |k|<=100
풀이
목표 : [a,b] 구간에 수를 연속해서 더하거나 빼는 문제 풀이 정리
[a,b] 구간에만 특정 값 k를 더해주는 방법에는 어떤 것이 있을까?
1. for 문을 이용해, a부터 b까지 k를 더해준다.
for index in range(a,b+1) :
arr[index] += k
하지만, 문제에서처럼 [a,b] 구간에 값들을 빼줄때도 있고 더해줄 때도 있다면, 각 연산마다 값을 변경하지 말고 모든 연산을 수행한 이후의 최종 변동률을 원본 배열에 반영해주는 방법은 없을까?
2. 누적합 이용하기
[a,b] 구간에만 k를 더해주면 변동률은 다음과 같다.
이는, 아래 배열의 누적합을 계산한 결과 배열과 동일한 것임을 알 수 있다.
즉, [a,b] 구간에 특정 값 k를 더할 때, 최종 변동률을 계산하는 방법은
- dp[a] = k, dp[b+1] = -k
- dp 배열의 누적합 계산 배열 = 최종 변동률
이다.
최종풀이
입출력 예
10 3
1 2 3 4 5 -1 -2 -3 -4 -5
1 5 -3
6 10 5
2 7 2
- 조교들의 각 지시가 a, b, k 일 때, 변동률 배열 dp의 dp[a] = k, dp[b+1] = -k 연산 수행
dp = [0] * (n+1)
for _ in range(m) :
a, b, k = map(int, input().split())
dp[a-1] += k
dp[b] += k*-1
2. 변동률 배열 dp의 누적합을 계산해주면, 최종 변동률을 얻을 수 있다.
for index in range(1,n) :
dp[index] += dp[index-1]
- 최종 변동률 배열(dp)과 원본 배열의 값을 더해주면, 연방장의 각 높이를 얻을 수 있다.
heights = list(map(int, input().split())
for index in range(n) :
heights[index] += dp[index]
코드
import sys
input = sys.stdin.readline
n, m = map(int, input().split())
heights = list(map(int, input().split()))
dp = [0] * (n+1)
for _ in range(m) :
a,b,k = map(int, input().split())
dp[a-1] += k
dp[b] += k*-1
for index in range(1, n) :
dp[index] += dp[index-1]
for i in range(n) :
heights[i] += dp[i]
print(" ".join(map(str,heights)))
Author And Source
이 문제에 관하여([Baekjoon] 19951. 태상이의 훈련소 생활), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@haman/Baekjoon-19951.-태상이의-훈련소-생활저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)