티스토리 뷰

https://www.acmicpc.net/problem/3653

 

3653번: 영화 수집

각 테스트 케이스에 대해서 한 줄에 m개의 정수를 출력해야 한다. i번째 출력하는 수는 i번째로 영화를 볼 때 그 영화의 위에 있었던 DVD의 개수이다. 상근이는 매번 영화를 볼 때마다 본 영화 DVD

www.acmicpc.net

// https://www.acmicpc.net/problem/3653
// 영화 수집

//세그먼트 트리 비재귀 구현
class Item {
	constructor(value = 0) {
		this.value = value;
	}
}

class NonRecursiveSegmentTree {
	constructor(inputArray) {
		// build
		this.n = inputArray.length;

		this.lg = Math.ceil(Math.log2(this.n));

		this.size = 1 << this.lg;

		this.tree = Array.from(new Array(this.size << 1), () => {
			return new Item();
		});

		//segemnt tree initial setting
		for (let i = 1; i <= this.n; i++) {
			this.tree[(i - 1) | this.size] = new Item(inputArray[i - 1]);
		}

		for (let i = this.size - 1; i > 0; --i) {
			this.tree[i] = this.merge(this.tree[i << 1], this.tree[(i << 1) | 1]);
		}
	}

	merge(nodeA, nodeB) {
		return new Item(nodeA.value + nodeB.value);
	}

	update(i, value) {
		i = (i - 1) | this.size;
		// console.log('update', i, value);
		const newValue = new Item(value);
		this.tree[i] = this.merge(this.tree[i], newValue);
		for (let j = 1; j <= this.lg; j++) {
			const k = i >> j;
			this.tree[k] = this.merge(this.tree[k << 1], this.tree[(k << 1) | 1]);
		}
	}

	//   l <= x < r  구간에 대한 쿼리
	query(l) {
		let L = new Item();
		let R = new Item();

		l = (l - 1) | this.size;
		let r = (this.size << 1) - 1;
		for (; l <= r; l >>= 1, r >>= 1) {
			if (l & 1) L = this.merge(L, this.tree[l++]);
			if (~r & 1) R = this.merge(this.tree[r--], R);
		}
		return this.merge(L, R);
	}
}

const input = require('fs').readFileSync('./dev/stdin').toString().trim().split('\n');
const T = +input.shift();
const answers = [];
for (let t = 0; t < T; t++) {
	const answer = [];
	// 영화는 총 n 개 있고 m번 꺼낼 예정
	const [n, m] = input.shift().split(' ').map(Number);

	let floor = n; //  꺼낸 영화가 위치하게될 층

	const end = n + m + 1;
	const floorMap = new Array(n);
	const arr = Array(end).fill(0);

	for (let i = 0; i < floor; i++) {
		arr[i] = 1; // i층에는 영화가 있다.
		floorMap[i] = floor - i - 1; // 영화 i 는  floor-i-1 층에 있다.
	}

	const segemntTree = new NonRecursiveSegmentTree(arr);
	const movieList = input
		.shift()
		.split(' ')
		.map((v) => Number(v) - 1);

	movieList.forEach((v) => {
		const nowFloor = floorMap[v]; // 지금 영화가 위치한 층
		const upper = segemntTree.query(nowFloor + 2); // 지금 영화보다 위에 있는 층에 있는 영화의 수
		answer.push(upper.value);
		segemntTree.update(nowFloor + 1, -1); // 지금 영화가 있는 층에서 해당 영화 제거
		floorMap[v] = floor++; // 새로운 영화 층
		segemntTree.update(floor, 1); // 새로운 층에 영화 추가
	});
	answers.push(answer.join(' '));
}
console.log(answers.join('\n'));
728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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
글 보관함