https://www.acmicpc.net/problem/18436
해당 문제는 수열의 특정 구간 내의 짝수 개수와 홀수 개수를 구하는 문제로, 세그먼트 트리 알고리즘을 사용하여 풀이했다.
1) 수열을 저장할 datas, pair(짝수 개수, 홀수 개수) 트리를 저장할 tree 배열을 선언한다. 이 때 트리의 크기는 수열 배열의 최대 크기의 4배 이상으로 설정한다.
2) 수의 개수 n을 입력받아 저장하고, n개의 수를 입력받아 datas에 저장한다. 이후 쿼리의 개수 m을 입력 받아 저장한다.
3) init() 함수를 통해 pair(짝수 개수, 홀수 개수) 트리를 초기화 한다.
4) m번의 쿼리를 실행한다.
update()를 실행하고, b번째 수를 c로 변경한다.update()는 하위 노드 값부터 상위 노드로 바뀌는 방식으로 진행한다.update() 함수 실행 이후 datas의 특정 인덱스 값도 변경해주어야 한다.get() 함수를 통해 현재 순서에서 구해야하는 범위의 짝수 개수 및 홀수 개수를 구한다.get()을 실행한다.#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<long long, int> pii; // 짝수, 홀수 개수
pii tree[400004];
int datas[100001];
int n, m;
pii init(int start, int end, int node)
{
if (start == end)
{
if (datas[start] % 2 == 0)
return tree[node] = pii(1, 0);
else
return tree[node] = pii(0, 1);
}
int mid = start + (end - start) / 2;
pii leftNode = init(start, mid, node * 2);
pii rightNode = init(mid + 1, end, node * 2 + 1);
return tree[node] = pii(leftNode.first + rightNode.first,
leftNode.second + rightNode.second);
}
pii get(int start, int end, int node, int left, int right)
{
if (end < left || right < start) return pii(0, 0);
if (left <= start && end <= right)
return tree[node];
int mid = start + (end - start) / 2;
pii leftNode = get(start, mid, node * 2, left, right);
pii rightNode = get(mid + 1, end, node * 2 + 1, left, right);
return pii(leftNode.first + rightNode.first, leftNode.second + rightNode.second);
}
pii update(int start, int end, int node, int index, int dif)
{
if (index < start || end < index) return tree[node];
if (start == end)
{
if (dif % 2 == 0)
return tree[node] = pii(1, 0);
else
return tree[node] = pii(0, 1);
}
int mid = start + (end - start) / 2;
pii leftNode = update(start, mid, node * 2, index, dif);
pii rightNode = update(mid + 1, end, node * 2 + 1, index, dif);
return tree[node] = pii(leftNode.first + rightNode.first, leftNode.second + rightNode.second);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> datas[i];
init(1, n, 1);
cin >> m;
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
if (a == 1)
{
update(1, n, 1, b, c);
datas[b] = c;
}
else if (a == 2)
cout << get(1, n, 1, b, c).first << '\n';
else
cout << get(1, n, 1, b, c).second << '\n';
}
}