티스토리 뷰
[BOJ 3392]화성 지도 - P2
문제 설명
N개의 직사각형 좌표(왼쪽 아래, 오른쪽 위)가 주어진다. N개의 직사각형을 모두 겹쳤을 때 총 넓이를 구해야한다.
문제 풀이
직사각형의 좌표값을 입력받을 때, 왼쪽 아래 좌표는 해당 직사각형이 차지하는 y좌표의 불을 켜는 것이고 오른쪽 위 좌표는 불을 끄는 행위라고 생각해보자. 우선 라인스위핑으로 접근하기 위해서 x좌표 오름차순으로 정렬한다. 정렬하고 나면 왼쪽 -> 오른쪽의 순서로 좌표를 살펴보게 되므로 현재넓이는 (현재 x좌표 값 - 지난 x좌표 값) * (높이의 총합) 으로 구할 수 있고, 이 값들을 모두 더하면 전체 넓이를 구할 수 있다.
그러면 이제 '넓이의 총합'을 구하기만 하면 된다. 넓이의 총합은 좌표의 범위에 해당하는 0 ~ 30000 까지 불이 켜져 있는 값이 모두 몇 개인지 세면 된다. 매번 0 ~ 30000을 세어보면 시간이 $O(N^{2})$가 되므로 초과된다. 이때 lazy propagation 의 아이디어를 차용해서 풀어볼 수 있다. [l,r] 범위 안에 모두 불이 켜져 있다면 해당 범위를 커버하는 segment tree의 값을 1 증가시키면 된다. 따라서 0 ~ 30000까지 직사각형 높이의 총 합은 루트노드인 len[1]배열만 찾아보면 된다.
소스 코드
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int SIZE = 30009;
#define START 1
#define END -1
vector<pair<pii,pii>> v;
int len[SIZE*8],cnt[SIZE*8];
int n,startIdx=1;
void update(int node,int cl,int cr,int ql,int qr,int diff){
if(cl > qr || ql > cr) return;
if(qr >= cr && ql <= cl) cnt[node] += diff;
else{
int mid = (cl+cr)/2;
update(node*2,cl,mid,ql,qr,diff);
update(node*2+1,mid+1,cr,ql,qr,diff);
}
if(cnt[node] >= 1) len[node] = cr - cl + 1;
else{
len[node] = len[node*2] + len[node*2+1];
}
}
int main(){
scanf("%d",&n);
for(;startIdx < 30000 ; startIdx *= 2);
for(int i=1 ; i<=n ; i++){
int x1,y1,x2,y2; scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
v.push_back({{x1,y1},{y2-y1, START}});
v.push_back({{x2,y1},{y2-y1, END}});
}
sort(v.begin(), v.end());
ll ans = 0;
int lastX = 0;
for(int i=0 ; i<v.size() ; i++){
int curX = v[i].first.first,curY = v[i].first.second,h = v[i].second.first,diff = v[i].second.second;
if(i > 0){
ll curArea = (curX - lastX) * 1LL * len[1];
ans += curArea;
}
update(1,1,startIdx,curY+1,curY + h - 1 + 1,diff); // 0 base
lastX = curX;
}
printf("%lld\n",ans);
return 0;
}
'Problem Solving > Segment Tree' 카테고리의 다른 글
[BOJ 10167] 금광 (0) | 2022.01.26 |
---|---|
[BOJ 15899]트리와 색깔 (0) | 2021.11.16 |
[BOJ 2820] 자동차 공장 (0) | 2021.11.16 |
[BOJ 2912]백설공주와 난쟁이 (0) | 2021.11.13 |
[BOJ 11658]구간 합 구하기3 (0) | 2021.11.13 |
댓글