※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 17773번 문제인 Fortune Telling이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/17773
예제 기준으로 검은 색 칸의 개수를 세면, 전체 칸수(NxM)에서 검은 칸수를 빼는 것으로 문제를 해결할 수 있다. 검은 칸 수를 구하는 방법을 생각해보자.
전체 직사각형들을 전부 그려두고 스위핑을 하는 관점으로 바라보면, 직사각형의 경계를 지날 때마다 다음 줄의 칸의 색이 변하는 것을 관찰할 수 있다. 스위핑을 하고 있는 줄을 하나의 배열로 생각하고, 이 배열의, 지나가는 직사각형 에지의 범위의 칸들을 뒤집는 연산을 lazy propagation이 적용된 세그먼트트리를 통해 관리한다면 이러한 넓이를 쉽게 구할 수 있을 것이다.
주어지는 수의 범위가 매우 크므로, 원래 좌표 사이의 거리를 알 수 있게끔 먼저 좌표압축을 하고 문제를 해결하자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
struct query {
int L, R, H;
query() {};
query(int L, int R, int H) {
this->L = L, this->R = R, this->H = H;
}
};
bool comp(query q1, query q2) {
return q1.H < q2.H;
}
query q[200000];
int arr[200001];
map<int, int> mp;
int seg[524289];
int lazy[524289];
void propagate(int L, int R, int sI) {
int len = arr[R + 1] - arr[L];
seg[sI] = len - seg[sI];
lazy[sI] = 0;
if (L < R) lazy[sI * 2] ^= 1, lazy[sI * 2 + 1] ^= 1;
}
int update(int L, int R, int qL, int qR, int sI) {
if (lazy[sI]) propagate(L, R, sI);
if (R < qL || qR < L) return seg[sI];
if (qL <= L && R <= qR) {
lazy[sI] = 1;
propagate(L, R, sI);
return seg[sI];
}
return seg[sI] = update(L, (L + R) / 2, qL, qR, sI * 2) + update((L + R) / 2 + 1, R, qL, qR, sI * 2 + 1);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
ll N, M; int K; cin >> N >> M >> K;
K <<= 1;
for (int i = 0; i < K; i += 2) {
int r1, r2, c1, c2; cin >> r1 >> r2 >> c1 >> c2;
arr[i] = c1, arr[i + 1] = c2 + 1;
q[i] = query(c1, c2 + 1, r1);
q[i + 1] = query(c1, c2 + 1, r2 + 1);
}
sort(arr, arr + K + 1);
int idx = 0, old = -1;
for (int i = 1; i <= K; i++) {
if (arr[i] == old) continue;
idx++;
old = arr[i];
arr[idx] = old;
mp.insert(make_pair(old, idx));
}
sort(q, q + K, comp);
ll ans = 0;
ll oldH = 0;
for (int i = 0; i < K;i++) {
auto& qry = q[i];
int L = qry.L, R = qry.R; ll H = qry.H;
ans += (H - oldH) * (ll) seg[1];
oldH = H;
update(1, idx, mp[L], mp[R] - 1, 1);
}
cout << N * M - ans;
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 15233 // C++] Final Score (0) | 2022.07.10 |
---|---|
[BOJ 14499 // C++] 주사위 굴리기 (0) | 2022.07.10 |
[BOJ 1637 // C++] 날카로운 눈 (0) | 2022.07.08 |
[BOJ 1646 // C++] 피이보나치 트리 (0) | 2022.07.07 |
[BOJ 2041 // C++] 숫자채우기 (0) | 2022.07.06 |