Problem Solving

BOJ 7626. 직사각형

thisisuserr 2024. 8. 26. 21:23

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

solved.ac: Platinum I (2024.09.10)

직사각형이 여러 개가 주어질 때 합집합의 넓이를 구하라는 문제다.

참 별 게 다 웰노운이다 싶다.

 

일단 x축 기준으로 쭉 정렬한 다음, 세로 선분들을 관리해주고 대충 스위핑질해주는 풀이이다.

 

세그먼트 트리 사용이 조금 특이하긴 하다.

 

두 가지 변수를 관리해주는데, 구간별 누적 길이랑 전체를 덮은 횟수를 기록해 준다.

전체를 덮은 횟수가 1 이상이라면 해당 구간의 값은 전체 길이와 동일하다.

그렇지 않다면 두 자식 노드로 쪼개고 그 합을 구하여 해결한다.

 

범위가 크니 좌표 압축을 해 주어야 한다.

딱히 쓸 게 없네요

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

using namespace std;
typedef long long int LL;

struct line
{
LL x;
LL y1, y2;
int val;

bool operator< (const line& l){return x < l.x;}
};

vector<line> lines;
vector<LL> comp;

LL tree[2000001], cnt[2000001];

void update(int node, int s, int e, int l, int r, int val)
{
  if(r < s || e < l) return;
  if(l <= s && e <= r) cnt[node] += val;
  else
  {
    int m = (s + e) / 2;
    update(node * 2, s, m, l, r, val);
    update(node * 2 + 1, m + 1, e, l, r, val);
  }

  if(cnt[node]) tree[node] = comp[e] - comp[s - 1];
  else
  {
    if(s == e) tree[node] = 0;
    else tree[node] = tree[node * 2] + tree[node * 2 + 1];
  }
}

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

  int n;
  cin >> n;
  for(int i = 0; i < n; i++)
    {
      LL x1, x2, y1, y2;
      cin >> x1 >> x2 >> y1 >> y2;

      lines.push_back({x1, y1, y2, 1});
      lines.push_back({x2, y1, y2, -1});
      comp.push_back(y1);
      comp.push_back(y2);
    }

  sort(comp.begin(), comp.end());
  comp.erase(unique(comp.begin(), comp.end()), comp.end());

  sort(lines.begin(), lines.end());

  LL res = 0;
  line prv = lines[0];

  for(int i = 0; i < 2 * n; i++)
    {
      line cur = lines[i];
      LL dx = cur.x - prv.x;
      res += tree[1] * dx;

      LL s = lower_bound(comp.begin(), comp.end(), cur.y1) - comp.begin();
      LL e = lower_bound(comp.begin(), comp.end(), cur.y2) - comp.begin();
      update(1, 1, comp.size() + 1, s + 1, e, cur.val);
      prv = cur;
    }
  cout << res;
}