3392 - 화성지도

코드

#include <stdio.h>
#include <tuple>
#include <vector>
#include <algorithm>
#define SIZE (30010 << 2)

using namespace std;

typedef tuple<int, int, int, int> P;

vector<P> p;
int tre[SIZE], cnt[SIZE];

void update(int l, int r, int node, int lo, int hi, int val) {
    if (r < lo || hi < l)
        return;
    if (lo <= l && r <= hi) {
        cnt[node] += val;
    }
    else {
        int mid = (l + r) / 2;
        update(l, mid, node * 2, lo, hi, val);
        update(mid + 1, r, node * 2 + 1, lo, hi, val);
    }
    if (cnt[node])
        tre[node] = r - l + 1;
    else {
        if (l == r)
            tre[node] = 0;
        else
            tre[node] = tre[node * 2] + tre[node * 2 + 1];
    }
}

int main()
{
    int n, i, x1, x2, y1, y2, psize, ans = 0, x, y;

    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        p.push_back(P(x1, y1, y2, 1));
        p.push_back(P(x2, y1, y2, -1));
    }
    sort(p.begin(), p.end());

    psize = n * 2;
    x = 0;
    y = 0;
    for (i = 0; i < psize; i++) {
        update(0, 30000, 1, get<1>(p[i]), get<2>(p[i]) - 1, get<3>(p[i]));
        if (i + 1 < psize && get<0>(p[i]) == get<0>(p[i + 1]))
            continue;
        ans += y * (get<0>(p[i]) - x);
        x = get<0>(p[i]);
        y = tre[1];
    }

    printf("%d", ans);

    return 0;
}

풀이

  • x 에 대해 y1, y2, 시작/종료 를 기록하여 plane sweeping 문제로 변경한다.
  • x로 정렬하고 y1 이상 y2 미만에 대해서 count 를 1증가 시킨다
  • count 가 1 이상인 영역에 대해 y2 - y1 값을 세그먼트 트리에 기재하고 누적합을 갱신
  • 전체 누적합을 조회하고, x의 차이값 만큼 곱하여 누적시키면 답이 나온다.
  • lazy propagation 이 필요할 것 같지만, 전체 조회만하기 때문에 구현 할 필요가 없다

results matching ""

    No results matching ""