일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 세그먼트 트리
- Overfitting
- 플로이드 와샬
- 가끔은_말로
- 백트래킹
- c++
- 크루스칼
- pytorch
- 자바스크립트
- object detection
- 너비 우선 탐색
- dfs
- dropout
- 분할 정복
- 회고록
- NEXT
- DP
- 알고리즘
- 미래는_현재와_과거로
- 문자열
- 2023
- 이분 탐색
- lazy propagation
- 다익스트라
- BFS
- back propagation
- tensorflow
- 우선 순위 큐
- 가끔은 말로
- 조합론
- Today
- Total
Doby's Lab
백준 17048번: 수열과 쿼리 24 (C++) 본문
https://www.acmicpc.net/problem/17408
17408번: 수열과 쿼리 24
길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오 1 i v: Ai를 v로 바꾼다. (1 ≤ i ≤ N, 1 ≤ v ≤ 109) 2 l r: l ≤ i < j ≤ r을 만족하는 모든 Ai + Aj 중에서
www.acmicpc.net
이번 문제는 각 구간 별로 최댓값 2개를 선별해내는 문제라고 생각하면 된다.
그러기 위해서 각 노드에 담겨있어야 하는 건 2개의 값으로 각 노드를 pair형으로 선언하기 때문에
트리 또한 pair형으로 선언하였다.
int arr[MAX];
pair<int, int> sgTree[MAX * 4];
트리를 init 하는 과정은 leaf node에 가면 한 노드에 2가지 값을 넣어야 하는데 배열 값 하나밖에 넣지 못한다.
이를 위해 pair 중 하나는 0을 넣어주었다.
>> INF 같은 엄청 큰 값은 안 된다. 트리를 구성하는 과정에 merge를 시키는데 큰 값을 순서로 뽑기 때문에 작은 값으로 할당한다.
void sgInit(int node, int start, int end){
if(start == end){
sgTree[node].first = 0;
sgTree[node].second = arr[start];
return;
}
int mid = (start + end) >> 1;
sgInit(node * 2, start, mid);
sgInit(node * 2 + 1, mid + 1, end);
sgTree[node] = merge(sgTree[node * 2], sgTree[node * 2 + 1]);
}
업데이트 또한 init함수를 바탕으로 구현하였다.
>> 다만, second에 배열 값을 할당해두었기 때문에 leaf node에 갔을 때, second를 바꿔주는 것을 인지해야 한다.
void update(int start, int end, int node, int idx, int value){
if(idx < start || end < idx) return;
if(start == end){
sgTree[node].second = value;
return;
}
int mid = (start + end) >> 1;
update(start, mid, node * 2, idx, value);
update(mid + 1, end, node * 2 + 1, idx, value);
sgTree[node] = merge(sgTree[node * 2], sgTree[node * 2 + 1]);
}
쿼리는 값 2개를 리턴 시키기 위해 pair형 함수로 구현하였다.
pair<int, int> query(int start, int end, int node, int left, int right){
if(left > end || right < start){
pair<int, int> none;
none.first = 0;
none.second = 0;
return none;
}
if(left <= start && end <= right){
return sgTree[node];
}
int mid = (start + end) >> 1;
return merge(query(start, mid, node * 2, left, right),
query(mid + 1, end, node * 2 + 1, left, right));
}
merge함수는 merge라 하기엔 애매하지만 global로 4 사이즈 크기에 배열을 선언해두고, pair변수 2개를 배열에 담아 정렬시켜서
값을 가져오도록 했다.
>> merge 안에서 배열을 선언하지 않은 이유는 혹시나 불필요한 메모리가 할당될까 봐 그랬다.
pair<int, int> merge(pair<int, int> a, pair<int, int> b){
mergeV[0] = a.first;
mergeV[1] = a.second;
mergeV[2] = b.first;
mergeV[3] = b.second;
sort(mergeV.begin(), mergeV.end());
a.first = mergeV[2];
a.second = mergeV[3];
return a;
}
[AC 코드]
#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
#define MAX (100000 + 1)
using namespace std;
int arr[MAX];
pair<int, int> sgTree[MAX * 4];
int n, m;
vector<int> mergeV(4);
pair<int, int> merge(pair<int, int> a, pair<int, int> b){
mergeV[0] = a.first;
mergeV[1] = a.second;
mergeV[2] = b.first;
mergeV[3] = b.second;
sort(mergeV.begin(), mergeV.end());
a.first = mergeV[2];
a.second = mergeV[3];
return a;
}
void sgInit(int node, int start, int end){
if(start == end){
sgTree[node].first = 0;
sgTree[node].second = arr[start];
return;
}
int mid = (start + end) >> 1;
sgInit(node * 2, start, mid);
sgInit(node * 2 + 1, mid + 1, end);
sgTree[node] = merge(sgTree[node * 2], sgTree[node * 2 + 1]);
}
void update(int start, int end, int node, int idx, int value){
if(idx < start || end < idx) return;
if(start == end){
sgTree[node].second = value;
return;
}
int mid = (start + end) >> 1;
update(start, mid, node * 2, idx, value);
update(mid + 1, end, node * 2 + 1, idx, value);
sgTree[node] = merge(sgTree[node * 2], sgTree[node * 2 + 1]);
}
pair<int, int> query(int start, int end, int node, int left, int right){
if(left > end || right < start){
pair<int, int> none;
none.first = 0;
none.second = 0;
return none;
}
if(left <= start && end <= right){
return sgTree[node];
}
int mid = (start + end) >> 1;
return merge(query(start, mid, node * 2, left, right),
query(mid + 1, end, node * 2 + 1, left, right));
}
int main(){;
cin >> n;
for(int i = 1; i <= n; i++){
cin >> arr[i];
}
sgInit(1, 1, n);
cin >> m;
vector<pair<int, int>> result; // 디버깅 때문에 pair형 배열로 선언
for(int i = 0; i < m; i++){
int q, a, b;
cin >> q >> a >> b;
if(q == 1){
update(1, n, 1, a, b);
}
else{
pair<int, int> p = query(1, n, 1, a, b);
result.push_back({p.first, p.second});
}
}
for(int i = 0; i < result.size(); i++){
//cout << result[i].first << ' ' << result[i].second << '\n';
cout << result[i].first + result[i].second << '\n';
}
return 0;
}
'PS > BOJ' 카테고리의 다른 글
백준 1005번: ACM Craft (C++) (0) | 2022.03.09 |
---|---|
백준 14567번: 선수과목 (Prerequisite) (C++), 위상 정렬 (0) | 2022.03.07 |
[자료구조] 백준 1043번: 거짓말 (C++) (0) | 2022.03.07 |
[알고리즘] 백준 1789번: 수들의 합 (C++) (0) | 2022.03.06 |
[자료구조] 백준 1717번: 집합의 표현 (C++) (0) | 2022.03.06 |