본문 바로가기
PS 문제 풀이/Baekjoon

[BOJ] 백준 8980 택배 (Segment Tree + Lazy Propagation)

by 까망 하르방 2021. 2. 27.
반응형

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

 Input 

4 40

6

3 4 20

1 2 10

1 3 20

1 4 30

2 3 10

2 4 20

 

 Output 

70

도착지 기준으로 박스들을 정렬한 뒤, (도착지가 가까울 수록 최대한 많이 실을 수 있기 때문)

박스를 최대한 많이 실을려고 시도합니다.

이때, 실을려는 박스(box[i]) 배달 구간 [box[i].s, box[i].e)에서 최대한 실을 수 있는 남은 공간을 빠르게 구해야 합니다.

 

다시말해, 구간 최대값을 구하는 Segment Tree를 구현하고 단말 노드에는 해당 구간에 실린 양을 표시합니다.

그렇다면 특정구간 [s, e)에서 박스를 싣고자 할 때,

C - query(1, 1, N, box[i].s, box[i].e - 1);로 빠르게 확인할 수 있습니다. 

 


#include <stdio.h>
typedef long long LL;
inline int max(int a, int b) { return (a > b) ? a : b; }
const int MAX_N = 1e5;
const int MAX_C = 1e8;
const int MAX_M = 2e5;
const int treeSize = 1 << 18;
struct BOX {
    // 보내는 마을 번호, 받는 마을 번호, 박수개수
    int s, e, cost;
}box[MAX_M + 10], trr[MAX_M + 10];
// 마을 수, 트럭 용량, 박스 정보 수
int N, C, M;
int tree[treeSize]; // 구간 최대값
int lazy[treeSize]; // lazy propagation
 
void InitTree(int n, int s, int e) {
    lazy[n] = tree[n] = 0;
    if (s == e) return;
    int L = n * 2, R = L + 1, m = (s + e) / 2;
    InitTree(L, s, m);
    InitTree(R, m + 1, e);
}
 
void LazyPropagation(int n, int s, int e) {
    if (lazy[n] == 0) return;
    tree[n] += lazy[n];// 구간 최대값
    if (s != e) {
        int L = n * 2, R = L + 1;
        lazy[L] += lazy[n];
        lazy[R] += lazy[n];
    }
    lazy[n] = 0;
}
 
int query(int n, int s, int e, int qs, int qe) {
    LazyPropagation(n, s, e);
    if ((qe < s) || (e < qs)) return 0;
    if ((qs <= s) && (e <= qe)) return tree[n];
    int L = n * 2, R = L + 1, m = (s + e) / 2;
    // 구간 최대값
    return max(query(L, s, m, qs, qe), query(R, m + 1, e, qs, qe));
}
 
void update(int n, int s, int e, int qs, int qe, int val) {
    LazyPropagation(n, s, e);
    int L = n * 2, R = L + 1, m = (s + e) / 2;
    if ((qe < s) || (e < qs)) return;
    if ((qs <= s) && (e <= qe)) {
        tree[n] += val;
        if (s != e) {
            lazy[L] += val;
            lazy[R] += val;
        }
        return;
    }
    update(L, s, m, qs, qe, val);
    update(R, m + 1, e, qs, qe, val);
    tree[n] = max(tree[L], tree[R]);
}
 
void mergeSort(int start, int end) {
    if (start >= end)
        return;
 
    int mid = (start + end) / 2;
    mergeSort(start, mid);
    mergeSort(mid + 1, end);
 
    int i = start, j = mid + 1, k = start;
    while (i <= mid && j <= end) {
        if (box[i].e <= box[j].e)
            trr[k++] = box[i++];
        else
            trr[k++] = box[j++];
    }
 
    while (i <= mid) trr[k++] = box[i++];
    while (j <= end) trr[k++] = box[j++];
    for (i = start; i <= end; i++)
        box[i] = trr[i];
}
 
void input() {
    scanf("%d %d", &N, &C);
    scanf("%d", &M);
    for (int i = 1; i <= M; ++i) {
        scanf("%d %d %d", &box[i].s, &box[i].e, &box[i].cost);
    }
}
 
LL solve() {
    LL sum = 0;
    // (받는 마을 기준) 오름차순 정렬
    mergeSort(1, M); 
    InitTree(1, 1, N);
    for (int i = 1; i <= M; i++) {
        // 해당 구간에서 배달할 수 있는 남은 용량
        int v = C - query(1, 1, N, box[i].s, box[i].e - 1);
 
        // 실을 수 있는 만큼만 싣기
        if (box[i].cost < v) v = box[i].cost;
        sum += v;
        // 해당 구간에 v가 실린 것을 표시
        update(1, 1, N, box[i].s, box[i].e - 1, v);
    }
    return sum;
}
 
int main() {
    // freopen("input.txt", "r", stdin);
    input();
    printf("%lld\n", solve());
}

 

반응형

'PS 문제 풀이 > Baekjoon' 카테고리의 다른 글

[BOJ] 백준 17612 쇼핑몰  (0) 2021.02.27
[BOJ] 백준 2549 루빅의 사각형  (0) 2021.02.27
[BOJ] 백준 8980 택배  (0) 2021.02.27
[BOJ] 백준 1922 네트워크 연결  (0) 2021.02.27
[BOJ] 백준 1197 최소 스패닝 트리  (0) 2021.02.27

댓글