티스토리 뷰
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에 대해 명령M개를 하나씩 더하면 O(NM) 시간초과
따로 계산할 수 있는 방법을 찾아 시간복잡도 줄이기
2. 부분합
명령 최종합을 O(NM) 보다 빠르게 구하려면?
명령의 최종합을 보면 명령의 시작과 끝까지 값이 동일한 것을 알 수 있다.
모든 명령의 시작과 끝만 기록하는건 O(M+2) 로 O(M) 시간 복잡도를 갖는다.
m[i]: 부분합 계산 전 명령 시작/끝 값 기록
단, 끝 값은 부분합에서 빼줘야 하기때문에 명령에 - 값을 처리
이제 부분합을 명령의 시작부터 끝부분까지 명령을 더하면 O(N) 시간 복잡도로 만들 수 있다.
sum[i]: i 번째 연변장에 더할 0부터 M까지의 명령합, 즉 명령의 부분합이 된다.
최종적으로, sum[i] = m[i] + sum[i-1] 계산
단 다음코드에서는 m[i]를 생략해서 sum에 시작과 끝을 기록
import com.sun.security.jgss.GSSUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[] arrN = new int[N];
st = new StringTokenizer(br.readLine());
for(int i = 0 ; i < N ; i++) {
arrN[i] = Integer.parseInt(st.nextToken());
}
int[] sum = new int[N + 1];
for(int i = 0 ; i < M ; i++) {
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
sum[a-1] += k;
sum[b] -= k;
}
for(int i = 1 ; i < N ; i++) {
sum[i] += sum[i-1];
}
StringBuilder sb = new StringBuilder();
for(int i = 0 ; i < N ; i++) {
arrN[i] += sum[i];
sb.append(arrN[i]).append(" ");
}
System.out.println(sb);
}
}
'CS > 알고리즘 풀이' 카테고리의 다른 글
[DP][백준 2293] 동전 1 (1) | 2024.11.01 |
---|---|
[DP 0-1 knapsack][백준 2616] 소형기관차 (0) | 2024.10.30 |
[PrefixSum][백준 3020] 개똥벌레 (0) | 2024.10.26 |
[Binray Search][백준 3020] 개똥벌레 (0) | 2024.10.26 |
[DP 0-1 knapsack][백준 12865] 평범한 배낭 (1) | 2024.10.22 |
- Total
- Today
- Yesterday
- Brainf**k 인터프리터
- 단체사진 찍기
- 17779
- 124 나라의 숫자
- 라면공장
- DP
- 찾아라 프로그래밍 마에스터
- 3954
- 2018 카카오 공채
- 주사위 윷놀이
- 카카오2020 공채
- 17825
- 후보키
- programmers
- 백준
- 프로그래머스
- 게리맨더링 2
- 정수 내림차순으로 배치하기
- 오블완
- 자바
- 2019 카카오 공채
- 티스토리챌린지
- 짝지어 제거하기
- 큰 수 만들기
- 괄호 변환
- java
- 가장 큰 정사각형 찾기
- 카카오 2020 공채
- 문자열을 정수로 바꾸기
- 투포인터
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |