본문 바로가기

CodeReview

BOJ 문제풀이 3

반응형

15975 화살표 그리기

N이 최대 10만입니다. 따라서 각각의 좌표마다 가장 가까운 좌표를 찾아주면 $O\left ( N^2 \right )$으로 TLE입니다.

주어진 좌표를 색상별로 정렬을 하고 각각의 색상 안에서 가장 가까운 좌표를 찾아줘야합니다.

저는 그냥 색을 기준으로 정렬시키고 그 이후 좌우에 있는 좌표를 보면서 더 가까운 좌표까지의 거리를 모두 더해주니 AC를 받았습니다.

색상별로 정렬이후 같은색끼리는 좌표기준으로 정렬을 한번 더 해줘야 할 것 같은데 *왜 맞았는지 모르겠습니다.

 

*pair를 sort해주면 first다음 second가 정렬되어 한번만 해주면 됩니다!

 

2042 구간 합 구하기

답이 long long인 것에 유의해야합니다.

전형적인 세그 트리 문제입니다.

쿼리당 $O\left ( N \right )$이 걸리고 처리해야할 쿼리가 M개임으로, 세그 트리를 이용해 쿼리를 $O\left ( logN \right )$으로 처리해야함을 통해 세그 트리 문제임을 알 수 있습니다.

업데이트 쿼리가 특정 노드에 값을 더해줄수도 빼줄수도 있는데 이는 아래와 같이 구현하여 해결할 수 있습니다.

	ll diff = c-arr[b];
        update(1, 1, h, b, diff);
        arr[b]=c;

구간의 max, min을 구할때와 달리 업데이트 쿼리가 비교적 쉽습니다.

void update(int node, int start, int end, int idx, ll diff) {
    if (idx<start || end<idx) return; // 노드가 관리하는 영역 밖이면 skip
    tree[node]+=diff; // 관리하는 영역 안이면 갱신
    if (start==end) return;
    int mid = (start+end)/2;
    update(2*node, start, mid, idx, diff);
    update(2*node+1, mid+1, end, idx, diff);
}

 

14438 수열과 쿼리 17

이번에는 min값을 구하는 세그 트리 문제입니다.

여기서는 기존과 다른 부분이 2가지 있습니다.

 

먼저 업데이트 쿼리를 받으면 배열의 값을 변경해주고 그 이후 업데이트 함수를 호출합니다.

arr[b]=c;
upd(1, 1, sz, b); // 노드 번호, 시작, 끝, 바꿀 인덱스

이렇게 정말 배열의 값을 먼저 변경해줍니다.

 

마지막으로 업데이트 함수에서 트리노드의 값도 변경합니다.

ll upd(int node, int start, int end, int idx) {
    if (idx<start || idx>end) return INF;
    if (start==end) {
        return tree[node]=arr[start];
    }
    int mid = (start+end)/2;
    upd(2*node, start, mid, idx);
    upd(2*node+1, mid+1, end, idx);
    return tree[node]=min(tree[2*node], tree[2*node+1]);
}

기존에 합을 구할때와 달리, 업데이트 이후 트리의 값을 갱신해주는 한 줄이 추가되야합니다.

 

2357 최솟값과 최댓값

세그 트리 문제입니다.

저는 get_num이라는 함수로 min, max를 동시에 구했습니다.

다만 이 문제를 풀면서 TLE를 몇번 받았는데, 이는 get함수에서 트리의 값을 갱신할 때 함수를 2번이 아니라 4번 호출했기 때문이었습니다.

아래처럼 구현해야 합니다.

pair<ll, ll> get_num(int node, int start, int end, int left, int right) {
    if (start>right || end<left) return mxMX;
    if (left<=start && right >=end) return tree[node];
    int mid = (start+end)/2;
    // call func twice not fourth
    pair<ll, ll> even = get_num(2*node, start, mid, left, right);
    pair<ll, ll> odd = get_num(2*node+1, mid+1, end, left, right);
    return {max(even.X, odd.X), min(even.Y, odd.Y)};
}

 

이 부분에서 한가지 궁금증이 생깁니다.* 추가예정

바로 "만약 쿼리를 그대로 4번 날려 갱신을 한다면, 시간복잡도는 기존과 상수배(2배) 차이가 날 뿐인데 어떻게 TLE를 받을 수 있을까?"입니다.

아무튼 쿼리를 4번 날려 TLE받은 코드는 이글을 보고 수정하여 AC를 받았습니다.

반응형

'CodeReview' 카테고리의 다른 글

BOJ 문제풀이 (W21)  (0) 2021.02.16
BOJ 문제풀이 4(W20)  (0) 2021.02.05
BOJ 문제풀이2  (0) 2021.01.06
BOJ 문제풀이 1  (0) 2021.01.05
BOJ 1202 보석도둑  (0) 2021.01.02