Skip to content

Commit

Permalink
09.30: dp(연속합 2)
Browse files Browse the repository at this point in the history
  • Loading branch information
luckylooky2 committed Sep 30, 2024
1 parent 05657f5 commit 08aff7b
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
32 changes: 32 additions & 0 deletions baekjoon/13398.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 연속합 2 : 동적 계획법
const input = require("fs")
.readFileSync(0, "utf-8")
.trim()
.split("\n")
.map((v) => v.split(" ").map((v) => +v));
const [n] = input.shift();
const arr = input.shift();
const dp = new Array(2).fill(null).map(() => new Array(n).fill(0));
let answer = -Infinity;

for (let i = 0; i < arr.length; i++) {
const curr = arr[i];
// no skip: 이전까지 더한 수보다 현재가 더 크다면, 현재로 초기화
dp[0][i] = Math.max(curr, (i > 0 ? dp[0][i - 1] : 0) + curr);
// skip
// - dp[0][i - 1]: 건너뛰지 않았을 때의 이전 항(현재를 건너뛴 경우)
// - dp[1][i - 1] + curr: 건너뛰었을 때의 이전 항(이전에서 건너뛴 경우 중 가장 최대값) + 현재 숫자
dp[1][i] = i > 0 ? Math.max(dp[0][i - 1], dp[1][i - 1] + curr) : -Infinity;
answer = Math.max(answer, dp[0][i], dp[1][i]);
}

console.log(answer);

// Try 1
// - no skip: 연속된 부호의 수를 하나로 더하고, 현재 음수일 때 다음 수가 더 크다면 음수를 포함하는 방법으로 계샨
// - skip: 특정 수를 제외해야 하기 때문에, 음수는 하나로 더하지 않고 배열로 묶음. 뒤에 나오는 양수보다 합이 큰 음수 묶음을 하나씩 순회하면서 합계를 구함

// Try 2 : 동적 계획법
// - 생각한 이유? 이전에 계산했던 값을 재사용할 수 있다고 생각
// - 0행: 건너뛰지 않았을 때, 현재 순서에서 최대값
// - 1행: 하나를 건너뛴 경우(현재 숫자 or 이전 숫자)를 포함하여, 현재 순서에서 최대값
91 changes: 91 additions & 0 deletions baekjoon/2268.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 수들의 합 7 : 세그먼트 트리
const input = require("fs")
.readFileSync(0, "utf-8")
.trim()
.split("\n")
.map((v) => v.split(" ").map((v) => +v));
const [n, m] = input.shift();
const modified = new Map();
const commands = input;
const [SUM, MODIFY] = [0, 1];
const answer = [];

const tree = [null];
const element = Array.from({ length: 10 }).fill(0);

function segmentTree(start, end, node = 1) {
if (start === end) return (tree[node] = start);
const mid = Math.floor((start + end) / 2);
const leftIndex = segmentTree(start, mid, 2 * node);
const rightIndex = segmentTree(mid + 1, end, 2 * node + 1);
// 구간에서 적용할 논리 : 합, 최대값, 최소값 ...
return (tree[node] = element[leftIndex] < element[rightIndex] ? leftIndex : rightIndex);
}

segmentTree(0, element.length - 1);

// function lowerBound(start, end, target, arr) {
// const mid = Math.floor((start + end) / 2);

// if (start === end) {
// return start;
// }

// if (arr[mid][0] >= target) {
// return lowerBound(start, mid, target, arr);
// } else {
// return lowerBound(mid + 1, end, target, arr);
// }
// }

// for (const [command, arg1, arg2] of commands) {
// if (command === SUM) {
// const small = Math.min(arg1, arg2);
// const big = Math.max(arg1, arg2);
// const entries = [...modified.entries()].sort((a, b) => a[0] - b[0]);
// let result = 0;
// // small보다 같거나 큰
// if (entries.length) {
// const index = lowerBound(0, entries.length - 1, small, entries);
// for (let i = index; i < entries.length; i++) {
// const [key, value] = entries[i];
// if (key > big) {
// break;
// }
// result += value;
// }
// }
// answer.push(result);
// } else if (command === MODIFY) {
// modified.set(arg1, arg2);
// }
// }

// console.log(answer.join("\n"));

// sums[1] = 1 ~ 1
// sums[3] = 1 ~ 3
// sums[6] = 1 ~ 5

// Sum(4, 5) = sums[5] - sums[3]
// Modify(4, 1)

// sums 배열 순회하며 최신화 => 시간을 줄여야 함
// - 1) 1/2 지점에서 왼쪽이면 왼쪽을 모두 -, 오른쪽이면 오른쪽을 모두 + 하는 방법 => 시간 초과 O(n / 2)
// - 2) Modify 버퍼에 모은 뒤, Sum이 되기 전에 sums에 적용 => 최악의 경우, 한 번씩 번갈아가며 O(500000 * 500000): 약 250초

// 세그먼트 트리? => 구현 불가
// - 요소가 n개인 세그먼트 트리
// - query, update 두 함수를 만들어야 함

// 상수 시간에 누적 값을 채우는 방법?
// - 모든 인덱스에 적용되는 것은 아니라서 하나의 값을 사용하기에는 어려움
// - 여러 값을 사용하기에는 순회해야 함

// 추가할 수 있는 것이 최대 백만 번이다
// - 0의 개수가 점점 줄어들 것 => 초반의 계산은 노가다?

// 1 2 3 4 5
// 0 0 0 1 1

// modify를 하면 sums의 해당 인덱스 뒤의 값이 모두 한 번에 더해져야 한다

0 comments on commit 08aff7b

Please sign in to comment.