-
[KOITP] 구간 합자료구조 및 알고리즘/문제풀이 2017. 1. 12. 08:06
출 처 : http://koitp.org/problem/SDS_PRO_3_5/read/
시간 제한 메모리 제한 제출 횟수 정답 횟수 (비율) 정답자 수 1.2 초 512 MB 2250 340 (15%) 279 < Comment >
이전 문제를 푸는데에 시간을 너무 많이 허비한 탓에 풀이를 듣고 풀었는데도, 구현하는데 꽤 걸렸습니다. 일단 Indexed Tree 구조를 이용하였고, 아마 그냥 풀었다면 매번 정렬하는 식으로 풀었을텐데, 확실히 해당방법을 이용하여 푸니 빠른 시간 내에 풀수 있었습니다.
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.StringTokenizer; public class SubSum { public static int N = 0; public static int Q = 0; public static int startIdx = 0; public static long subSum[] = null; public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); N = Integer.parseInt(br.readLine()); Q = Integer.parseInt(br.readLine()); makeIndexedTree(N); StringTokenizer st = null; int isQ = 0; int num1 = 0; int num2 = 0; long subSum = 0; for (int i = 0 ; i < Q ; i++) { st = new StringTokenizer(br.readLine()); isQ = Integer.parseInt(st.nextToken()); num1 = Integer.parseInt(st.nextToken()); num2 = Integer.parseInt(st.nextToken()); if (isQ == 1) { // 구간합 구하기 subSum = getSubSum(startIdx + num1 - 1, startIdx + num2 - 1); bw.write("" + subSum + "\n"); } else { // 구간합 갱신하기 updateSubSum(startIdx + num1 - 1, num2); } } bw.flush(); bw.close(); } public static void makeIndexedTree (int n) { int treeNum = 0; int width = 0; int depth = 0; while (true) { width = (int)Math.pow(2, depth++); treeNum += width; if (width >= n) { break; } } subSum = new long[treeNum + 1]; startIdx = (int) Math.pow(2, depth - 1); for (int i = 0 ; i < n ; i++) { subSum[startIdx + i] = i + 1; } int parentNodeIdx = 0; for (int i = treeNum ; i > 0 ; i --) { if (i % 2 == 0) { parentNodeIdx = i / 2; subSum[parentNodeIdx] = subSum[i] + subSum[i+1]; } } } public static void updateSubSum (int idx, long updNum) { subSum[idx] = updNum; int parentNodeIdx = idx / 2; if (parentNodeIdx == 0) { return; } long parentUpdNum = 0; if (idx % 2 == 0) { parentUpdNum = subSum[idx] + subSum[idx + 1]; } else { parentUpdNum = subSum[idx - 1] + subSum[idx]; } updateSubSum(parentNodeIdx, parentUpdNum); } public static long getSubSum(int head, int tail) { if (tail - head == 1) { return subSum[head] + subSum[tail]; } else if (tail == head) { return subSum[head]; } int parentIdx = 0; boolean headIsEven = ( head % 2 == 0 ? true : false ); boolean tailIsOdd = ( tail % 2 == 1 ? true : false ); if (headIsEven && tailIsOdd) { return getSubSum(head / 2, tail / 2); } else if (!headIsEven && tailIsOdd) { return subSum[head] + getSubSum(head + 1, tail); } else if (headIsEven && !tailIsOdd) { return getSubSum(head, tail - 1) + subSum[tail]; } else { return subSum[head] + getSubSum(head + 1, tail - 1) + subSum[tail]; } } }