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';
}
}