※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 8217번 문제인 유성이다.
문제는 아래 링크를 확인하자.

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

 

8217번: 유성

첫째 줄에 두 정수 N, M (1 ≤ N, M ≤ 300,000)이 주어진다. N은 BIU연합의 회원국 개수고, M은 행성 궤도의 구역 개수이다. 둘째 줄에는 M개의 정수 oi (1 ≤ oi ≤ N)가 주어진다. oi는 i번째 구역을 소

www.acmicpc.net

유성우가 내리는 전체 시뮬레이션은 구간의 각 값을 val씩 증가시키는 업데이트를 지원하는, lazy propagation을 이용하는 세그먼트트리로 간단히 구현 가능하다.

 

문제의 답의 범위를 적절히 정하고 mid번째 유성우까지 내렸을 때의 각 국가별 운석 수집량을 이용해 모든 국가의 이분탐색을 한 단계 진행시킬 수 있다. 이러한 탐색을 유성우가 내리는 시뮬레이션을 lg번 진행해 모든 쿼리의 답을 구하고 문제를 해결하자.

 

글쓴이는 시간초과에 유의해 int와 적절한 MAX값을 이용해 구현해 문제를 해결했다.

 

아래는 제출한 소스코드이다.

#define MAX 1000000007
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

int lazy[1048577];

void update(int L, int R, int qL, int qR, int qVal, int sI) {
	if (R < qL || qR < L) return;
	if (qL <= L && R <= qR) lazy[sI] = min(lazy[sI] + qVal, MAX);
	else update(L, (L + R) / 2, qL, qR, qVal, sI * 2), update((L + R) / 2 + 1, R, qL, qR, qVal, sI * 2 + 1);
}

int pointval(int qI) {
	int L = 1, R = 524288, sI = 1;
	while (L < R) {
		if (lazy[sI]) {
			lazy[sI * 2] = min(lazy[sI * 2] + lazy[sI], MAX), lazy[sI * 2 + 1] = min(lazy[sI * 2 + 1] + lazy[sI], MAX);
			lazy[sI] = 0;
		}
		int mid = (L + R) / 2;
		if (mid < qI) L = mid + 1, sI = sI * 2 + 1;
		else R = mid, sI = sI * 2;
	}
	return lazy[sI];
}

struct comet {
	int L, R, qVal;
	comet() {};
	comet(int L, int R, int qVal) {
		this->L = L, this->R = R, this->qVal = qVal;
	}
};

int C;
comet comets[300000];

int N; // sector 수
vector<int> sectors[300001]; // [q]: q번 쿼리의 섹터

struct query {
	int idx;
	int low, high, mid;
	int goal;
};

bool qcomp(query& q1, query& q2) {
	return q1.mid < q2.mid;
}
bool qcomp2(query& q1, query& q2) {
	return q1.idx < q2.idx;
}

int Q;
query queries[300000];

void PBS() {
	memset(lazy, 0, sizeof(lazy));
	sort(queries, queries + Q, qcomp);

	int ci = 0, qi = 0;
	while (ci < C && qi < Q) {
		if (ci <= queries[qi].mid) {
			if (comets[ci].L <= comets[ci].R) {
				update(1, 524288, comets[ci].L, comets[ci].R, comets[ci].qVal, 1);
			}
			else {
				update(1, 524288, comets[ci].L, 524288, comets[ci].qVal, 1), update(1, 524288, 1, comets[ci].R, comets[ci].qVal, 1);
			}
			
			ci++;
		}
		else {
			if (queries[qi].low < queries[qi].high) {
				int total = 0;
				for (auto& x : sectors[queries[qi].idx]) {
					total = min(total + pointval(x), MAX);
				}

				if (total < queries[qi].goal) queries[qi].low = queries[qi].mid + 1;
				else queries[qi].high = queries[qi].mid;

				queries[qi].mid = (queries[qi].low + queries[qi].high) / 2;
			}
			qi++;
		}
	}
	while (qi < Q) {
		if (queries[qi].low < queries[qi].high) {
			int total = 0;
			for (auto& x : sectors[queries[qi].idx]) {
				total = min(total + pointval(x), MAX);
			}

			if (total < queries[qi].goal) queries[qi].low = queries[qi].mid + 1;
			else queries[qi].high = queries[qi].mid;

			queries[qi].mid = (queries[qi].low + queries[qi].high) / 2;
		}
		qi++;
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> Q >> N;
	for (int i = 1; i <= N; i++) {
		int q; cin >> q;
		sectors[q].emplace_back(i);
	}

	for (int i = 0; i < Q; i++) {
		query& q = queries[i];
		q.idx = i + 1;
		cin >> q.goal;
	}

	cin >> C;
	for (int i = 0; i < C; i++) {
		comet& c = comets[i];
		cin >> c.L >> c.R >> c.qVal;
	}
	for (int i = 0; i < Q; i++) {
		query& q = queries[i];
		q.low = 0, q.high = C;
		q.mid = (q.low + q.high) / 2;
	}

	for (int i = 0; i < 19; i++) {
		PBS();
	}

	sort(queries, queries + Q, qcomp2);
	for (int i = 0; i < Q; i++) {
		if (queries[i].low == C) cout << "NIE" << '\n';
		else cout << queries[i].low + 1 << '\n';
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 13557 // C++] 수열과 쿼리 10  (0) 2022.07.27
[BOJ 15957 // C++] 음악 추천  (0) 2022.07.26
[BOJ 15811 // C++] 복면산?!  (0) 2022.07.24
[BOJ 12355 // C++] Ocean View (Large)  (0) 2022.07.24
[BOJ 15564 // C++] Äventyr 2  (0) 2022.07.24

+ Recent posts