https://www.acmicpc.net/problem/1395
1395번: 스위치
문제 준규네 집에는 총 N개의 스위치가 있고 이를 편하게 1번부터 N번까지 차례대로 번호를 매겼다. 그리고 준규의 취미는 이 스위치들을 켜고 끄는 것이다. 준규가 하는 스위치를 갖고 노는 일은 크게 두 가지이다. 하나는 A번부터 B번 사이의 스위치 상태를 반전시키는 것이고 다른 하나는 C번부터 D번 사이의 스위치 중 켜져 있는 상태의 스위치의 개수를 세는 것이다. 하지만 준규가 싫증을 느껴 우리가 이 귀찮은 일을 떠맡게 되었고 프로그래밍을 통해 일을 처리
www.acmicpc.net
문제의 분류가 세그먼트 트리 with Lazy Propagation 이다. 밑의 문제를 풀 수 있다면, 세그먼트 트리를 구성하는 연산 기호만 잘 바꿔주면 쉽게 풀 수 있는 문제이다.
https://www.acmicpc.net/problem/10999
10999번: 구간 합 구하기 2
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)과 M(1 ≤ M ≤ 10,000), K(1 ≤ K ≤ 10,000) 가 주어진다. M은 수의 변경이 일어나는 회수이고, K는 구간의 합을 구하는 회수이다. 그리고 둘째 줄부터 N+1번째 줄까지 N개의 수가 주어진다. 그리고 N+2번째 줄부터 N+M+K+1번째 줄까지 세 개의 정수 a, b, c 또는 a, b, c, d가 주어지는데, a가 1인 경우 b번째 수부터 c번째 수에 d를 더하고, a가 2
www.acmicpc.net
#include <iostream> using namespace std; #define MAX_N 100000 #define endl '\n' int seg[MAX_N*4]; bool lazy[MAX_N*4]; void update_lazy(int now, int start, int end) { if (lazy[now] == true) { seg[now] = (end - start + 1) - seg[now]; if (start != end) { lazy[now * 2] = (lazy[now * 2]) ? false : true; lazy[now * 2 + 1] = (lazy[now * 2 + 1]) ? false : true; } lazy[now] = false; } } void update_range(int now, int left, int right, int start, int end) { update_lazy(now, start, end); if (left > end || right < start) return; if (left <= start && end <= right) { seg[now] = (end - start + 1) - seg[now]; if (start != end) { lazy[now * 2] = (lazy[now * 2]) ? false : true; lazy[now * 2 + 1] = (lazy[now * 2 + 1]) ? false : true; } return; } int mid = (start + end) / 2; update_range(now * 2, left, right, start, mid); update_range(now * 2 + 1, left, right, mid + 1, end); seg[now] = seg[now * 2] + seg[now * 2 + 1]; } int query(int now, int left, int right, int start, int end) { update_lazy(now, start, end); if (left > end || right < start) return 0; if (left <= start && end <= right) { return seg[now]; } int mid = (start + end) / 2; return( query(now * 2, left, right, start, mid) + query(now * 2 + 1, left, right, mid + 1, end) ); } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int N, Q; cin >> N >> Q; for (int i = 0; i < Q; i++) { int tag; cin >> tag; if (tag == 0) { // 반전 int s, e; cin >> s >> e; update_range(1, s - 1, e - 1, 0, N - 1); } else { // on의 갯수 int s, e; cin >> s >> e; cout << query(1, s - 1, e - 1, 0, N - 1) << endl; } } }
'알고리즘 > [C++]BOJ' 카테고리의 다른 글
[백준BOJ] 6118 숨바꼭질 (0) | 2019.10.05 |
---|---|
[백준BOJ] 10999 구간 합 구하기 2 (0) | 2019.10.04 |
[백준BOJ] 1626 두 번째로 작은 스패닝 트리 (0) | 2019.10.03 |