SlideShare a Scribd company logo
#1—
세그먼트트리느리게업데이트하기
Lazy Propagation on Segment Trees
by
Suhyun Park
Sogang ICPC Team – 2020 겨울 고급 스터디 acm.sogang.ac.kr
환영합니다!
Sogang ICPC Team 1
“고급” 스터디에 오신 여러분을 환영합니다!
환영합니다!
Sogang ICPC Team 2
저는...
✓ 박수현 – @shiftpsh / shiftpsh.com
✓ Sogang ICPC Team 전임 학회장 – 2019년
✓ ICPC 2019 Seoul Regional에 팀 Redshift로 참가 – 8위
✓ solved.ac를 만든 사람!
“고급” 스터디를 시작하기 전에...
Sogang ICPC Team 3
“고급” 스터디는 초급이나 중급 스터디와는 진행방식이 좀 다릅니다
✓ 옆 동네에서 하는 팀 빌딩이나 모의고사 등 재밌는 것들 → 없어요
✓ 기본적으로 혼자 열심히 하셔야 해요
– 여기 오실 정도의 여러분들이 PS에 미친 분들이라는 건 확실해 보이니 걱정하지
않겠습니다
“고급” 스터디를 시작하기 전에...
Sogang ICPC Team 4
다루게 되는 것들
✓ solved.ac 기준으로 에서 사이의 문제들
✓ 실무에서는 전혀 쓸 것 같지 않고 실제로도 별로 안 쓰이는 생소한 알고리즘과
자료구조들
– 하지만 대회에서는 나온다
✓ 여하튼 ICPC 등의 “대회 준비”에 초점이 맞춰져 있습니다
“고급” 스터디를 시작하기 전에...
Sogang ICPC Team 5
“고급”에 붙어 있는 따옴표는 뭐에요?
✓ 고급 스터디에서 다루는 자료구조와 알고리즘들은 대회 준비의 필요조건이지
충분조건이 아닙니다
– 이런 거 많이 아는 것보다 이미 아는 알고리즘을 잘 써먹는 방법을 공부하는 게
대회 성적에 훨씬 도움이 됩니다
✓ 진짜 “고급” – 이미 알고 있는 알고리즘들을 잘 써먹는 능력을 기르는 스터디
– 팀 연습 등
“고급” 스터디를 시작하기 전에...
Sogang ICPC Team 6
그럼 이거 왜 하는 거에요?
✓ 모르면 아예 못 푸는 내용들을 대비하기 위해
✓ 남들한테는 다 웰노운인데 나한테만 아닌 것들을 나에게도 웰노운으로 만들어 써먹기
위해
– 팀노트에 적어가세요
✓ solved.ac 경험치 올리기 위해
Remarks on Segment Trees
Sogang ICPC Team 7
1–10
1–5 6–10
1–3 4–5 6–8 9–10
1–2 3 4 5 6–7 8 9 10
1 2 6 7
f (x, s, e, · · · ) = f
(
2x, s,
⌊
s + e
2
⌋
, · · ·
)
+ f
(
2x + 1,
⌊
s + e
2
⌋
+ 1, e, · · ·
)
Remarks on Segment Trees
Sogang ICPC Team 8
1–10
1–5 6–10
1–3 4–5 6–8 9–10
1–2 3 4 5 6–7 8 9 10
1 2 6 7
A5 · · · A9 의 합?
Remarks on Segment Trees
Sogang ICPC Team 9
✓ Al · · · Ar 의 합 쿼리 = O (log n)
✓ Ai 업데이트 = O (log n)
Lazy Propagation
Sogang ICPC Team 10
✓ Al · · · Ar 의 합 쿼리
✓ Al · · · Ar 업데이트
의 두 쿼리를 처리해야 한다고 생각해 보자
– 하나하나 업데이트한다면 쿼리 한 번에 O ((r − l) log n) → 사실상 O (n log n)
Lazy Propagation
Sogang ICPC Team 11
쿼리 한 번에 O (n log n)은 느려도 너무 느리다
→ 업데이트할 때 매번 리프 노드까지 보내지 말자
→ 트리를 하나 더 만들어서 거기다 업데이트하고 쿼리할 때 한꺼번에 업데이트하자
Lazy Propagation
Sogang ICPC Team 12
40 ll a[1000001], tree[1048576 * 2], lazy[1048576 * 2];
41
42 void _propagate(int x, int s, int e) {
43 if (!lazy[x]) return;
44 tree[x] += (e - s + 1) * lazy[x];
45 if (s != e) {
46 lazy[x * 2] += lazy[x];
47 lazy[x * 2 + 1] += lazy[x];
48 }
49 lazy[x] = 0;
50 }
lazy라는 이름으로 별도의 트리를 만든다
Lazy Propagation
Sogang ICPC Team 13
40 ll a[1000001], tree[1048576 * 2], lazy[1048576 * 2];
41
42 void _propagate(int x, int s, int e) {
43 if (!lazy[x]) return;
44 tree[x] += (e - s + 1) * lazy[x];
45 if (s != e) {
46 lazy[x * 2] += lazy[x];
47 lazy[x * 2 + 1] += lazy[x];
48 }
49 lazy[x] = 0;
50 }
노드 x에 아직 업데이트하지 않은 값이 있다면 트리에 업데이트해주는 메서드
Lazy Propagation
Sogang ICPC Team 14
52 ll _sum(int x, int s, int e, int l, int r) {
53 _propagate(x, s, e);
54 if (l > e || r < s) return 0;
55 if (l <= s && e <= r) return tree[x];
56 int m = (s + e) / 2;
57 return _sum(x * 2 , s, m, l, r) +
58 _sum(x * 2 + 1, m + 1, e, l, r);
59 }
합 쿼리를 계산할 때 propagation을 해 줘야 한다
Lazy Propagation
Sogang ICPC Team 15
61 void _update(int x, int s, int e, int l, int r, ll dv) {
62 _propagate(x, s, e);
63 if (l > e || r < s) return;
64 if (l <= s && e <= r) {
65 tree[x] += (e - s + 1) * dv;
66 if (s != e) {
67 lazy[x * 2] += dv;
68 lazy[x * 2 + 1] += dv;
69 }
70 return;
71 }
72 int m = (s + e) / 2;
73 _update(x * 2 , s, m, l, r, dv);
74 _update(x * 2 + 1, m + 1, e, l, r, dv);
75 tree[x] = tree[x * 2] + tree[x * 2 + 1];
76 }
업데이트할 때도 propagation을 해 줘야 한다
Lazy Propagation
Sogang ICPC Team 16
61 void _update(int x, int s, int e, int l, int r, ll dv) {
62 _propagate(x, s, e);
63 if (l > e || r < s) return;
64 if (l <= s && e <= r) {
65 tree[x] += (e - s + 1) * dv;
66 if (s != e) {
67 lazy[x * 2] += dv;
68 lazy[x * 2 + 1] += dv;
69 }
70 return;
71 }
72 int m = (s + e) / 2;
73 _update(x * 2 , s, m, l, r, dv);
74 _update(x * 2 + 1, m + 1, e, l, r, dv);
75 tree[x] = tree[x * 2] + tree[x * 2 + 1];
76 }
현재 확인하는 구간이 업데이트 구간 안에 있다면 리프 노드까지 가지 않고 lazy를
업데이트하고 끝낸다
Lazy Propagation
Sogang ICPC Team 17
89 ll sum(int l, int r) {
90 return _sum(1, 1, 1000000, l, r);
91 }
92
93 void update(int l, int r, ll dv) {
94 _update(1, 1, 1000000, l, r, dv);
95 }
96
97 void initialize() {
98 _initialize(1, 1, 1000000);
99 }
_initialize는 세그먼트 트리의 그것과 같으므로 생략
구간 합 구하기 2 #
10999
Sogang ICPC Team 18
✓ n ≤ 106
✓ m + k ≤ 20000
구현해보자
구간 합 구하기 2 #
10999
Sogang ICPC Team 19
115 while (q--) {
116 int op, l, r;
117 cin >> op >> l >> r;
118 if (op == 1) {
119 ll dv;
120 cin >> dv;
121 update(l, r, dv);
122 } else { // op == 2
123 cout << sum(l, r) << 'n';
124 }
125 }
source code
JuQueen #
10277
Sogang ICPC Team 20
코어가 4, 587, 520개인 컴퓨터의 클럭을 변경하는 프로그램을 짜야 한다. N 단계의 클럭이
가능하고
✓ CPU x의 클럭을 s단계만큼 증감
✓ CPU a · · · b의 클럭을 s단계만큼 증감
✓ CPU x의 클럭 단계 출력
중 하나를 할 수 있다.
클럭은 한 단계씩만 올라가거나 내려가며, 여러 코어에 대해 여러 단계를 한꺼번에 증감할
경우 그 중 하나라도 0단계나 N 단계에 도달하면 증감을 종료하고 증감한 만큼의 단계를
출력한다.
JuQueen #
10277
Sogang ICPC Team 21
클럭은 한 단계씩만 올라가거나 내려가며, 여러 코어에 대해 여러 단계를 한꺼번에 증감할
경우 그 중 하나라도 0단계나 N 단계에 도달하면 증감을 종료하고 증감한 만큼의 단계를
출력한다.
✓ 지금 클럭들이 1, 2, 3, 4고 N = 6이라면, 클럭 4단계를 올리라는 명령을 내린다면 2
단계만 올라가고 끝난다
JuQueen #
10277
Sogang ICPC Team 22
CPU a · · · b의 클럭 단계의 최솟값을 mn, 최댓값을 mx라 하고, s만큼 증감하고자 한다면
✓ mx + s > N 이라면? N − mx만큼만 올릴 수 있다
✓ mn + s < 0이라면? mn만큼만 내릴 수 있다
✓ 둘 다 아니라면 s만큼 올릴 수 있다
JuQueen #
10277
Sogang ICPC Team 23
세 가지 연산을 할 수 있는 자료구조가 필요
✓ 인덱스 l · · · r에서의 최솟값 구하기
✓ 인덱스 l · · · r에서의 최댓값 구하기
✓ 인덱스 l · · · r을 전부 s만큼 증가시키기
하나의 원소 i에 대해서만 연산할 경우 l = r = i
JuQueen #
10277
Sogang ICPC Team 24
A = {a0, a1, · · · , an}
A′
= {a0 + d, a1 + d, · · · , an + d}
이라고 하면
max
a′∈A′
(
a′
)
= max
a∈A
(a) + d
min
a′∈A′
(
a′
)
= min
a∈A
(a) + d
이 성립 → 그냥 더해주면 된다. 별 문제 없다
JuQueen #
10277
Sogang ICPC Team 25
✓ 인덱스 l · · · r에서의 최솟값 구하기
✓ 인덱스 l · · · r에서의 최댓값 구하기
· · · 를 하기 위해 세그먼트 트리를 튜플 ⟨min, max⟩ 로 만들고
✓ 인덱스 l · · · r을 전부 s만큼 증가시키기
· · · 를 하기 위해 lazy propagate 하면 되겠다!
JuQueen #
10277
Sogang ICPC Team 26
40 struct mii {
41 ll mn, mx;
42 };
43
44 mii tree[8388608 * 2];
45 int lazy[8388608 * 2];
46
47 int inf = 987654321;
48 int c, n, o;
source code
first, second는 헷갈리니까 struct를 새로 만든다. 어차피 정렬할 것도 아닌데· · ·
JuQueen #
10277
Sogang ICPC Team 27
50 void _propagate(int x, int s, int e) {
51 if (!lazy[x]) return;
52 tree[x].mn += lazy[x];
53 tree[x].mx += lazy[x];
54 if (s != e) {
55 lazy[x * 2] += lazy[x];
56 lazy[x * 2 + 1] += lazy[x];
57 }
58 lazy[x] = 0;
59 }
source code
Propagation – 더해주는 쿼리를 처리해 주기 위함
JuQueen #
10277
Sogang ICPC Team 28
61 ll _minimum(int x, int s, int e, int l, int r) {
62 _propagate(x, s, e);
63 if (l > e || r < s) return inf;
64 if (l <= s && e <= r) return tree[x].mn;
65 int m = (s + e) / 2;
66 return min(_minimum(x * 2, s, m, l, r),
67 _minimum(x * 2 + 1, m + 1, e, l, r));
68 }
source code
구간 최솟값 쿼리를 처리하면서 propagation도 같이 한다
JuQueen #
10277
Sogang ICPC Team 29
70 ll _maximum(int x, int s, int e, int l, int r) {
71 _propagate(x, s, e);
72 if (l > e || r < s) return 0;
73 if (l <= s && e <= r) return tree[x].mx;
74 int m = (s + e) / 2;
75 return max(_maximum(x * 2, s, m, l, r),
76 _maximum(x * 2 + 1, m + 1, e, l, r));
77 }
source code
최댓값에 대해서도 동일하게 처리해 준다
JuQueen #
10277
Sogang ICPC Team 30
79 void _update(int x, int s, int e, int l, int r, ll dv) {
80 _propagate(x, s, e);
81 if (l > e || r < s) return;
82 if (l <= s && e <= r) {
83 tree[x].mn += dv;
84 tree[x].mx += dv;
85 if (s != e) {
86 lazy[x * 2] += dv;
87 lazy[x * 2 + 1] += dv;
88 }
89 return;
90 }
91 int m = (s + e) / 2;
92 _update(x * 2 , s, m, l, r, dv);
93 _update(x * 2 + 1, m + 1, e, l, r, dv);
94 tree[x].mn = min(tree[x * 2].mn, tree[x * 2 + 1].mn);
95 tree[x].mx = max(tree[x * 2].mx, tree[x * 2 + 1].mx);
96 }
source code
JuQueen #
10277
Sogang ICPC Team 31
98 ll minimum(int l, int r) {
99 return _minimum(1, 0, c - 1, l, r);
100 }
101
102 ll maximum(int l, int r) {
103 return _maximum(1, 0, c - 1, l, r);
104 }
105
106 void update(int l, int r, ll dv) {
107 _update(1, 0, c - 1, l, r, dv);
108 }
source code
함수 인자가 너무 많으면 헷갈리므로 개인적으로는 첫 호출을 하는 함수를 따로 만들어서
사용하는 중
JuQueen #
10277
Sogang ICPC Team 32
118 string op;
119 cin >> op;
120 if (op[0] == 's') { // ”state”
121 int x;
122 cin >> x;
123 cout << minimum(x, x) << 'n';
124 } else if (op[0] == 'g') { // ”groupchange”
source code
값을 구하는 쿼리는 따로 만들 필요 없이 최솟값이나 최댓값 쿼리로 해결 가능하다
JuQueen #
10277
Sogang ICPC Team 33
124 } else if (op[0] == 'g') { // ”groupchange”
125 int a, b, s;
126 cin >> a >> b >> s;
127
128 ll mn = minimum(a, b), mx = maximum(a, b);
129 if (s > 0 && s + mx > n) {
130 update(a, b, n - mx);
131 cout << n - mx << 'n';
132 } else if (s < 0 && s + mn < 0) {
133 update(a, b, -mn);
134 cout << -mn << 'n';
135 } else {
136 update(a, b, s);
137 cout << s << 'n';
138 }
139 } else { // ”change”
source code
구간 최대/최소를 구해서 증감할 수 있는 만큼 증감해 주고 결과를 출력한다
JuQueen #
10277
Sogang ICPC Team 34
139 } else { // ”change”
140 int x, s;
141 cin >> x >> s;
142
143 ll val = minimum(x, x);
144 if (s > 0 && s + val > n) {
145 update(x, x, n - val);
146 cout << n - val << 'n';
147 } else if (s < 0 && s + val < 0) {
148 update(x, x, -val);
149 cout << -val << 'n';
150 } else {
151 update(x, x, s);
152 cout << s << 'n';
153 }
154 }
155 }
source code
마찬가지.
Lazy Propagation Not on Segment Trees
Sogang ICPC Team 35
Lazy propagation의 아이디어는 세그먼트 트리에 한정해서 쓰이지 않는다
Pixel Triangles #
16572
Sogang ICPC Team 36
2, 000 × 2, 000 크기의 격자 판이 주어지며, 각 픽셀(칸)은 행과 열을 이용해서 위치가
표시된다. 가장 왼쪽 열이 1열, 가장 위쪽 행이 1행이다.
이 때 픽셀 삼각형의 정의는 다음과 같다.
✓ 픽셀 삼각형은 3개의 자연수 A, B, C 에 대해서 P (A, B, C)로 표현된다.
✓ P (A, B, C) = {(x, y) | A ≤ x, B ≤ y, 0 ≤ (x − A) + (y − B) ≤ C − 1}
격자 위의 픽셀들로 구성된 픽셀 삼각형이 n ≤ 4, 000, 000개 주어졌을 때, 픽셀 삼각형들이
덮는 픽셀의 개수를 출력해라.
Pixel Triangles #
16572
Sogang ICPC Team 37
P (1, 2, 3) = {(x, y) | 1 ≤ x, 2 ≤ y, 0 ≤ (x − 1) + (y − 2) ≤ 3 − 1}
Pixel Triangles #
16572
Sogang ICPC Team 38
P (3, 1, 2) = {(x, y) | 3 ≤ x, 1 ≤ y, 0 ≤ (x − 3) + (y − 1) ≤ 2 − 1}
Pixel Triangles #
16572
Sogang ICPC Team 39
P (5, 5, 1) = {(x, y) | 5 ≤ x, 5 ≤ y, 0 ≤ (x − 5) + (y − 5) ≤ 1 − 1}
Pixel Triangles #
16572
Sogang ICPC Team 40
이 때 최종적으로 덮어지는 픽셀의 개수는 9개가 된다
Pixel Triangles #
16572
Sogang ICPC Team 41
최악의 경우?
✓ P (0, 0, 2000)이 4, 000, 000개 있음
✓ bool 배열에 나이브하게 채워넣는다면 배열 액세스 횟수
4, 000, 000 ×
2, 000 (2, 000 + 1)
2
Lazy propagation의 아이디어를 어떻게 적용할 수 있을까?
Pixel Triangles #
16572
Sogang ICPC Team 42
삼각형의 왼쪽 위 꼭짓점에 삼각형의 크기를 미리 적어두자
0 3 0 0 0
0 0 0 0 0
2 0 0 0 0
0 0 0 0 0
0 0 0 0 1
Pixel Triangles #
16572
Sogang ICPC Team 43
모든 픽셀을 왼쪽 오른쪽, 위 아래 순서대로 보면서, 지금 확인하고 있는 칸 ≥ 2라면 오른쪽
칸과 아랫쪽 칸을 갱신
0 3 2 0 0
0 2 0 0 0
2 0 0 0 0
0 0 0 0 0
0 0 0 0 1
Pixel Triangles #
16572
Sogang ICPC Team 44
삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다
0 3 2 1 0
0 2 1 0 0
2 0 0 0 0
0 0 0 0 0
0 0 0 0 1
Pixel Triangles #
16572
Sogang ICPC Team 45
삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다
0 3 2 1 0
0 2 1 0 0
2 1 0 0 0
0 0 0 0 0
0 0 0 0 1
Pixel Triangles #
16572
Sogang ICPC Team 46
삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다
0 3 2 1 0
0 2 1 0 0
2 1 0 0 0
1 0 0 0 0
0 0 0 0 1
Pixel Triangles #
16572
Sogang ICPC Team 47
작업이 끝나면 1 이상이 적힌 칸의 수는 9개!
0 3 2 1 0
0 2 1 0 0
2 1 0 0 0
1 0 0 0 0
0 0 0 0 1
소스는 생략
1회차 연습문제
Sogang ICPC Team 48
✓ 구간 합 구하기 2 #
10999
✓ JuQueen #
10277
✓ Pixel Triangles #
16572
1. 스위치 #
1395
2. XOR #
12844
3. 하늘에서 떨어지는 1, 2, · · · , R − L + 1개의 별 #
17353
4. 수열과 쿼리 13 #
13925
5. Range GCD #
12858

More Related Content

What's hot

게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
Seungmo Koo
 
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
Taehoon Kim
 
Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편
준철 박
 
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
Taehoon Kim
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규ChangKyu Song
 
파이썬으로 익히는 딥러닝 기본 (18년)
파이썬으로 익히는 딥러닝 기본 (18년)파이썬으로 익히는 딥러닝 기본 (18년)
파이썬으로 익히는 딥러닝 기본 (18년)
SK(주) C&C - 강병호
 
추천시스템 이제는 돈이 되어야 한다.
추천시스템 이제는 돈이 되어야 한다.추천시스템 이제는 돈이 되어야 한다.
추천시스템 이제는 돈이 되어야 한다.
choi kyumin
 
취미로 엔진 만들기
취미로 엔진 만들기취미로 엔진 만들기
취미로 엔진 만들기
Jiho Choi
 
밑바닥부터 시작하는딥러닝 8장
밑바닥부터 시작하는딥러닝 8장밑바닥부터 시작하는딥러닝 8장
밑바닥부터 시작하는딥러닝 8장
Sunggon Song
 
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
JungHyun Hong
 
秘密分散法の数理
秘密分散法の数理秘密分散法の数理
秘密分散法の数理
Akito Tabira
 
그럴듯한 랜덤 생성 컨텐츠 만들기
그럴듯한 랜덤 생성 컨텐츠 만들기그럴듯한 랜덤 생성 컨텐츠 만들기
그럴듯한 랜덤 생성 컨텐츠 만들기
Yongha Kim
 
카카오톡으로 여친 만들기 2013.06.29
카카오톡으로 여친 만들기 2013.06.29카카오톡으로 여친 만들기 2013.06.29
카카오톡으로 여친 만들기 2013.06.29
Taehoon Kim
 
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
NAVER D2
 
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
Taehoon Kim
 
zk-SNARKsの仕組みについて
zk-SNARKsの仕組みについてzk-SNARKsの仕組みについて
zk-SNARKsの仕組みについて
ts21
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
Hibiki Yamashiro
 
혼자서 만드는 MMO게임 서버
혼자서 만드는 MMO게임 서버혼자서 만드는 MMO게임 서버
혼자서 만드는 MMO게임 서버
iFunFactory Inc.
 
高速フーリエ変換
高速フーリエ変換高速フーリエ変換
高速フーリエ変換
AtCoder Inc.
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
Seungmo Koo
 

What's hot (20)

게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
게임서버프로그래밍 #0 - TCP 및 이벤트 통지모델
 
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
책 읽어주는 딥러닝: 배우 유인나가 해리포터를 읽어준다면 DEVIEW 2017
 
Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편Python 게임서버 안녕하십니까 : RPC framework 편
Python 게임서버 안녕하십니까 : RPC framework 편
 
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기 DEVIEW 2016
 
[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규[NDC08] 최적화와 프로파일링 - 송창규
[NDC08] 최적화와 프로파일링 - 송창규
 
파이썬으로 익히는 딥러닝 기본 (18년)
파이썬으로 익히는 딥러닝 기본 (18년)파이썬으로 익히는 딥러닝 기본 (18년)
파이썬으로 익히는 딥러닝 기본 (18년)
 
추천시스템 이제는 돈이 되어야 한다.
추천시스템 이제는 돈이 되어야 한다.추천시스템 이제는 돈이 되어야 한다.
추천시스템 이제는 돈이 되어야 한다.
 
취미로 엔진 만들기
취미로 엔진 만들기취미로 엔진 만들기
취미로 엔진 만들기
 
밑바닥부터 시작하는딥러닝 8장
밑바닥부터 시작하는딥러닝 8장밑바닥부터 시작하는딥러닝 8장
밑바닥부터 시작하는딥러닝 8장
 
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
[GomGuard] 뉴런부터 YOLO 까지 - 딥러닝 전반에 대한 이야기
 
秘密分散法の数理
秘密分散法の数理秘密分散法の数理
秘密分散法の数理
 
그럴듯한 랜덤 생성 컨텐츠 만들기
그럴듯한 랜덤 생성 컨텐츠 만들기그럴듯한 랜덤 생성 컨텐츠 만들기
그럴듯한 랜덤 생성 컨텐츠 만들기
 
카카오톡으로 여친 만들기 2013.06.29
카카오톡으로 여친 만들기 2013.06.29카카오톡으로 여친 만들기 2013.06.29
카카오톡으로 여친 만들기 2013.06.29
 
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
딥러닝과 강화 학습으로 나보다 잘하는 쿠키런 AI 구현하기
 
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
머신러닝 해외 취업 준비: 닳고 닳은 이력서와 고통스러웠던 면접을 돌아보며 SNU 2018
 
zk-SNARKsの仕組みについて
zk-SNARKsの仕組みについてzk-SNARKsの仕組みについて
zk-SNARKsの仕組みについて
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
혼자서 만드는 MMO게임 서버
혼자서 만드는 MMO게임 서버혼자서 만드는 MMO게임 서버
혼자서 만드는 MMO게임 서버
 
高速フーリエ変換
高速フーリエ変換高速フーリエ変換
高速フーリエ変換
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 

Similar to 세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter

Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Suhyun Park
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
JinTaek Seo
 
확통 회귀분석
확통 회귀분석확통 회귀분석
확통 회귀분석
jaypi Ko
 
Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019
Suhyun Park
 
하스켈 성능 튜닝
하스켈 성능 튜닝하스켈 성능 튜닝
하스켈 성능 튜닝
민석 이
 
R 스터디 첫번째
R 스터디 첫번째R 스터디 첫번째
R 스터디 첫번째
Jaeseok Park
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
beom kyun choi
 
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기
Woong won Lee
 
2019 ppc answers
2019 ppc answers2019 ppc answers
2019 ppc answers
승혁 조
 
딥러닝기본-신경망기초
딥러닝기본-신경망기초딥러닝기본-신경망기초
딥러닝기본-신경망기초
jaypi Ko
 
Variational AutoEncoder(VAE)
Variational AutoEncoder(VAE)Variational AutoEncoder(VAE)
Variational AutoEncoder(VAE)
강민국 강민국
 
Code로 이해하는 RNN
Code로 이해하는 RNNCode로 이해하는 RNN
Code로 이해하는 RNN
SANG WON PARK
 
Coursera Machine Learning으로 기계학습 배우기 : week2
Coursera Machine Learning으로 기계학습 배우기 : week2Coursera Machine Learning으로 기계학습 배우기 : week2
Coursera Machine Learning으로 기계학습 배우기 : week2
Kwangsik Lee
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서KimChangHoen
 
해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3
Haesun Park
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpKimjeongmoo
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
Han Sung Kim
 
R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작
Terry Cho
 

Similar to 세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter (20)

Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
Lazy Propagation on Segment Trees - Sogang ICPC Team, 2019
 
3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택3ds maxscript 튜토리얼_20151206_서진택
3ds maxscript 튜토리얼_20151206_서진택
 
확통 회귀분석
확통 회귀분석확통 회귀분석
확통 회귀분석
 
Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019Persistent Segment Tree - Sogang ICPC Team, 2019
Persistent Segment Tree - Sogang ICPC Team, 2019
 
하스켈 성능 튜닝
하스켈 성능 튜닝하스켈 성능 튜닝
하스켈 성능 튜닝
 
R 스터디 첫번째
R 스터디 첫번째R 스터디 첫번째
R 스터디 첫번째
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
 
RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기RLCode와 A3C 쉽고 깊게 이해하기
RLCode와 A3C 쉽고 깊게 이해하기
 
2019 ppc answers
2019 ppc answers2019 ppc answers
2019 ppc answers
 
Rdatamining
Rdatamining Rdatamining
Rdatamining
 
딥러닝기본-신경망기초
딥러닝기본-신경망기초딥러닝기본-신경망기초
딥러닝기본-신경망기초
 
Variational AutoEncoder(VAE)
Variational AutoEncoder(VAE)Variational AutoEncoder(VAE)
Variational AutoEncoder(VAE)
 
Code로 이해하는 RNN
Code로 이해하는 RNNCode로 이해하는 RNN
Code로 이해하는 RNN
 
Coursera Machine Learning으로 기계학습 배우기 : week2
Coursera Machine Learning으로 기계학습 배우기 : week2Coursera Machine Learning으로 기계학습 배우기 : week2
Coursera Machine Learning으로 기계학습 배우기 : week2
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서
 
R_datamining
R_dataminingR_datamining
R_datamining
 
해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3해커에게 전해들은 머신러닝 #3
해커에게 전해들은 머신러닝 #3
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 Hwp
 
파이썬 스터디 2주차
파이썬 스터디 2주차파이썬 스터디 2주차
파이썬 스터디 2주차
 
R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작R 프로그래밍-향상된 데이타 조작
R 프로그래밍-향상된 데이타 조작
 

세그먼트 트리 느리게 업데이트하기 - Sogang ICPC Team, 2020 Winter

  • 1. #1— 세그먼트트리느리게업데이트하기 Lazy Propagation on Segment Trees by Suhyun Park Sogang ICPC Team – 2020 겨울 고급 스터디 acm.sogang.ac.kr
  • 2. 환영합니다! Sogang ICPC Team 1 “고급” 스터디에 오신 여러분을 환영합니다!
  • 3. 환영합니다! Sogang ICPC Team 2 저는... ✓ 박수현 – @shiftpsh / shiftpsh.com ✓ Sogang ICPC Team 전임 학회장 – 2019년 ✓ ICPC 2019 Seoul Regional에 팀 Redshift로 참가 – 8위 ✓ solved.ac를 만든 사람!
  • 4. “고급” 스터디를 시작하기 전에... Sogang ICPC Team 3 “고급” 스터디는 초급이나 중급 스터디와는 진행방식이 좀 다릅니다 ✓ 옆 동네에서 하는 팀 빌딩이나 모의고사 등 재밌는 것들 → 없어요 ✓ 기본적으로 혼자 열심히 하셔야 해요 – 여기 오실 정도의 여러분들이 PS에 미친 분들이라는 건 확실해 보이니 걱정하지 않겠습니다
  • 5. “고급” 스터디를 시작하기 전에... Sogang ICPC Team 4 다루게 되는 것들 ✓ solved.ac 기준으로 에서 사이의 문제들 ✓ 실무에서는 전혀 쓸 것 같지 않고 실제로도 별로 안 쓰이는 생소한 알고리즘과 자료구조들 – 하지만 대회에서는 나온다 ✓ 여하튼 ICPC 등의 “대회 준비”에 초점이 맞춰져 있습니다
  • 6. “고급” 스터디를 시작하기 전에... Sogang ICPC Team 5 “고급”에 붙어 있는 따옴표는 뭐에요? ✓ 고급 스터디에서 다루는 자료구조와 알고리즘들은 대회 준비의 필요조건이지 충분조건이 아닙니다 – 이런 거 많이 아는 것보다 이미 아는 알고리즘을 잘 써먹는 방법을 공부하는 게 대회 성적에 훨씬 도움이 됩니다 ✓ 진짜 “고급” – 이미 알고 있는 알고리즘들을 잘 써먹는 능력을 기르는 스터디 – 팀 연습 등
  • 7. “고급” 스터디를 시작하기 전에... Sogang ICPC Team 6 그럼 이거 왜 하는 거에요? ✓ 모르면 아예 못 푸는 내용들을 대비하기 위해 ✓ 남들한테는 다 웰노운인데 나한테만 아닌 것들을 나에게도 웰노운으로 만들어 써먹기 위해 – 팀노트에 적어가세요 ✓ solved.ac 경험치 올리기 위해
  • 8. Remarks on Segment Trees Sogang ICPC Team 7 1–10 1–5 6–10 1–3 4–5 6–8 9–10 1–2 3 4 5 6–7 8 9 10 1 2 6 7 f (x, s, e, · · · ) = f ( 2x, s, ⌊ s + e 2 ⌋ , · · · ) + f ( 2x + 1, ⌊ s + e 2 ⌋ + 1, e, · · · )
  • 9. Remarks on Segment Trees Sogang ICPC Team 8 1–10 1–5 6–10 1–3 4–5 6–8 9–10 1–2 3 4 5 6–7 8 9 10 1 2 6 7 A5 · · · A9 의 합?
  • 10. Remarks on Segment Trees Sogang ICPC Team 9 ✓ Al · · · Ar 의 합 쿼리 = O (log n) ✓ Ai 업데이트 = O (log n)
  • 11. Lazy Propagation Sogang ICPC Team 10 ✓ Al · · · Ar 의 합 쿼리 ✓ Al · · · Ar 업데이트 의 두 쿼리를 처리해야 한다고 생각해 보자 – 하나하나 업데이트한다면 쿼리 한 번에 O ((r − l) log n) → 사실상 O (n log n)
  • 12. Lazy Propagation Sogang ICPC Team 11 쿼리 한 번에 O (n log n)은 느려도 너무 느리다 → 업데이트할 때 매번 리프 노드까지 보내지 말자 → 트리를 하나 더 만들어서 거기다 업데이트하고 쿼리할 때 한꺼번에 업데이트하자
  • 13. Lazy Propagation Sogang ICPC Team 12 40 ll a[1000001], tree[1048576 * 2], lazy[1048576 * 2]; 41 42 void _propagate(int x, int s, int e) { 43 if (!lazy[x]) return; 44 tree[x] += (e - s + 1) * lazy[x]; 45 if (s != e) { 46 lazy[x * 2] += lazy[x]; 47 lazy[x * 2 + 1] += lazy[x]; 48 } 49 lazy[x] = 0; 50 } lazy라는 이름으로 별도의 트리를 만든다
  • 14. Lazy Propagation Sogang ICPC Team 13 40 ll a[1000001], tree[1048576 * 2], lazy[1048576 * 2]; 41 42 void _propagate(int x, int s, int e) { 43 if (!lazy[x]) return; 44 tree[x] += (e - s + 1) * lazy[x]; 45 if (s != e) { 46 lazy[x * 2] += lazy[x]; 47 lazy[x * 2 + 1] += lazy[x]; 48 } 49 lazy[x] = 0; 50 } 노드 x에 아직 업데이트하지 않은 값이 있다면 트리에 업데이트해주는 메서드
  • 15. Lazy Propagation Sogang ICPC Team 14 52 ll _sum(int x, int s, int e, int l, int r) { 53 _propagate(x, s, e); 54 if (l > e || r < s) return 0; 55 if (l <= s && e <= r) return tree[x]; 56 int m = (s + e) / 2; 57 return _sum(x * 2 , s, m, l, r) + 58 _sum(x * 2 + 1, m + 1, e, l, r); 59 } 합 쿼리를 계산할 때 propagation을 해 줘야 한다
  • 16. Lazy Propagation Sogang ICPC Team 15 61 void _update(int x, int s, int e, int l, int r, ll dv) { 62 _propagate(x, s, e); 63 if (l > e || r < s) return; 64 if (l <= s && e <= r) { 65 tree[x] += (e - s + 1) * dv; 66 if (s != e) { 67 lazy[x * 2] += dv; 68 lazy[x * 2 + 1] += dv; 69 } 70 return; 71 } 72 int m = (s + e) / 2; 73 _update(x * 2 , s, m, l, r, dv); 74 _update(x * 2 + 1, m + 1, e, l, r, dv); 75 tree[x] = tree[x * 2] + tree[x * 2 + 1]; 76 } 업데이트할 때도 propagation을 해 줘야 한다
  • 17. Lazy Propagation Sogang ICPC Team 16 61 void _update(int x, int s, int e, int l, int r, ll dv) { 62 _propagate(x, s, e); 63 if (l > e || r < s) return; 64 if (l <= s && e <= r) { 65 tree[x] += (e - s + 1) * dv; 66 if (s != e) { 67 lazy[x * 2] += dv; 68 lazy[x * 2 + 1] += dv; 69 } 70 return; 71 } 72 int m = (s + e) / 2; 73 _update(x * 2 , s, m, l, r, dv); 74 _update(x * 2 + 1, m + 1, e, l, r, dv); 75 tree[x] = tree[x * 2] + tree[x * 2 + 1]; 76 } 현재 확인하는 구간이 업데이트 구간 안에 있다면 리프 노드까지 가지 않고 lazy를 업데이트하고 끝낸다
  • 18. Lazy Propagation Sogang ICPC Team 17 89 ll sum(int l, int r) { 90 return _sum(1, 1, 1000000, l, r); 91 } 92 93 void update(int l, int r, ll dv) { 94 _update(1, 1, 1000000, l, r, dv); 95 } 96 97 void initialize() { 98 _initialize(1, 1, 1000000); 99 } _initialize는 세그먼트 트리의 그것과 같으므로 생략
  • 19. 구간 합 구하기 2 # 10999 Sogang ICPC Team 18 ✓ n ≤ 106 ✓ m + k ≤ 20000 구현해보자
  • 20. 구간 합 구하기 2 # 10999 Sogang ICPC Team 19 115 while (q--) { 116 int op, l, r; 117 cin >> op >> l >> r; 118 if (op == 1) { 119 ll dv; 120 cin >> dv; 121 update(l, r, dv); 122 } else { // op == 2 123 cout << sum(l, r) << 'n'; 124 } 125 } source code
  • 21. JuQueen # 10277 Sogang ICPC Team 20 코어가 4, 587, 520개인 컴퓨터의 클럭을 변경하는 프로그램을 짜야 한다. N 단계의 클럭이 가능하고 ✓ CPU x의 클럭을 s단계만큼 증감 ✓ CPU a · · · b의 클럭을 s단계만큼 증감 ✓ CPU x의 클럭 단계 출력 중 하나를 할 수 있다. 클럭은 한 단계씩만 올라가거나 내려가며, 여러 코어에 대해 여러 단계를 한꺼번에 증감할 경우 그 중 하나라도 0단계나 N 단계에 도달하면 증감을 종료하고 증감한 만큼의 단계를 출력한다.
  • 22. JuQueen # 10277 Sogang ICPC Team 21 클럭은 한 단계씩만 올라가거나 내려가며, 여러 코어에 대해 여러 단계를 한꺼번에 증감할 경우 그 중 하나라도 0단계나 N 단계에 도달하면 증감을 종료하고 증감한 만큼의 단계를 출력한다. ✓ 지금 클럭들이 1, 2, 3, 4고 N = 6이라면, 클럭 4단계를 올리라는 명령을 내린다면 2 단계만 올라가고 끝난다
  • 23. JuQueen # 10277 Sogang ICPC Team 22 CPU a · · · b의 클럭 단계의 최솟값을 mn, 최댓값을 mx라 하고, s만큼 증감하고자 한다면 ✓ mx + s > N 이라면? N − mx만큼만 올릴 수 있다 ✓ mn + s < 0이라면? mn만큼만 내릴 수 있다 ✓ 둘 다 아니라면 s만큼 올릴 수 있다
  • 24. JuQueen # 10277 Sogang ICPC Team 23 세 가지 연산을 할 수 있는 자료구조가 필요 ✓ 인덱스 l · · · r에서의 최솟값 구하기 ✓ 인덱스 l · · · r에서의 최댓값 구하기 ✓ 인덱스 l · · · r을 전부 s만큼 증가시키기 하나의 원소 i에 대해서만 연산할 경우 l = r = i
  • 25. JuQueen # 10277 Sogang ICPC Team 24 A = {a0, a1, · · · , an} A′ = {a0 + d, a1 + d, · · · , an + d} 이라고 하면 max a′∈A′ ( a′ ) = max a∈A (a) + d min a′∈A′ ( a′ ) = min a∈A (a) + d 이 성립 → 그냥 더해주면 된다. 별 문제 없다
  • 26. JuQueen # 10277 Sogang ICPC Team 25 ✓ 인덱스 l · · · r에서의 최솟값 구하기 ✓ 인덱스 l · · · r에서의 최댓값 구하기 · · · 를 하기 위해 세그먼트 트리를 튜플 ⟨min, max⟩ 로 만들고 ✓ 인덱스 l · · · r을 전부 s만큼 증가시키기 · · · 를 하기 위해 lazy propagate 하면 되겠다!
  • 27. JuQueen # 10277 Sogang ICPC Team 26 40 struct mii { 41 ll mn, mx; 42 }; 43 44 mii tree[8388608 * 2]; 45 int lazy[8388608 * 2]; 46 47 int inf = 987654321; 48 int c, n, o; source code first, second는 헷갈리니까 struct를 새로 만든다. 어차피 정렬할 것도 아닌데· · ·
  • 28. JuQueen # 10277 Sogang ICPC Team 27 50 void _propagate(int x, int s, int e) { 51 if (!lazy[x]) return; 52 tree[x].mn += lazy[x]; 53 tree[x].mx += lazy[x]; 54 if (s != e) { 55 lazy[x * 2] += lazy[x]; 56 lazy[x * 2 + 1] += lazy[x]; 57 } 58 lazy[x] = 0; 59 } source code Propagation – 더해주는 쿼리를 처리해 주기 위함
  • 29. JuQueen # 10277 Sogang ICPC Team 28 61 ll _minimum(int x, int s, int e, int l, int r) { 62 _propagate(x, s, e); 63 if (l > e || r < s) return inf; 64 if (l <= s && e <= r) return tree[x].mn; 65 int m = (s + e) / 2; 66 return min(_minimum(x * 2, s, m, l, r), 67 _minimum(x * 2 + 1, m + 1, e, l, r)); 68 } source code 구간 최솟값 쿼리를 처리하면서 propagation도 같이 한다
  • 30. JuQueen # 10277 Sogang ICPC Team 29 70 ll _maximum(int x, int s, int e, int l, int r) { 71 _propagate(x, s, e); 72 if (l > e || r < s) return 0; 73 if (l <= s && e <= r) return tree[x].mx; 74 int m = (s + e) / 2; 75 return max(_maximum(x * 2, s, m, l, r), 76 _maximum(x * 2 + 1, m + 1, e, l, r)); 77 } source code 최댓값에 대해서도 동일하게 처리해 준다
  • 31. JuQueen # 10277 Sogang ICPC Team 30 79 void _update(int x, int s, int e, int l, int r, ll dv) { 80 _propagate(x, s, e); 81 if (l > e || r < s) return; 82 if (l <= s && e <= r) { 83 tree[x].mn += dv; 84 tree[x].mx += dv; 85 if (s != e) { 86 lazy[x * 2] += dv; 87 lazy[x * 2 + 1] += dv; 88 } 89 return; 90 } 91 int m = (s + e) / 2; 92 _update(x * 2 , s, m, l, r, dv); 93 _update(x * 2 + 1, m + 1, e, l, r, dv); 94 tree[x].mn = min(tree[x * 2].mn, tree[x * 2 + 1].mn); 95 tree[x].mx = max(tree[x * 2].mx, tree[x * 2 + 1].mx); 96 } source code
  • 32. JuQueen # 10277 Sogang ICPC Team 31 98 ll minimum(int l, int r) { 99 return _minimum(1, 0, c - 1, l, r); 100 } 101 102 ll maximum(int l, int r) { 103 return _maximum(1, 0, c - 1, l, r); 104 } 105 106 void update(int l, int r, ll dv) { 107 _update(1, 0, c - 1, l, r, dv); 108 } source code 함수 인자가 너무 많으면 헷갈리므로 개인적으로는 첫 호출을 하는 함수를 따로 만들어서 사용하는 중
  • 33. JuQueen # 10277 Sogang ICPC Team 32 118 string op; 119 cin >> op; 120 if (op[0] == 's') { // ”state” 121 int x; 122 cin >> x; 123 cout << minimum(x, x) << 'n'; 124 } else if (op[0] == 'g') { // ”groupchange” source code 값을 구하는 쿼리는 따로 만들 필요 없이 최솟값이나 최댓값 쿼리로 해결 가능하다
  • 34. JuQueen # 10277 Sogang ICPC Team 33 124 } else if (op[0] == 'g') { // ”groupchange” 125 int a, b, s; 126 cin >> a >> b >> s; 127 128 ll mn = minimum(a, b), mx = maximum(a, b); 129 if (s > 0 && s + mx > n) { 130 update(a, b, n - mx); 131 cout << n - mx << 'n'; 132 } else if (s < 0 && s + mn < 0) { 133 update(a, b, -mn); 134 cout << -mn << 'n'; 135 } else { 136 update(a, b, s); 137 cout << s << 'n'; 138 } 139 } else { // ”change” source code 구간 최대/최소를 구해서 증감할 수 있는 만큼 증감해 주고 결과를 출력한다
  • 35. JuQueen # 10277 Sogang ICPC Team 34 139 } else { // ”change” 140 int x, s; 141 cin >> x >> s; 142 143 ll val = minimum(x, x); 144 if (s > 0 && s + val > n) { 145 update(x, x, n - val); 146 cout << n - val << 'n'; 147 } else if (s < 0 && s + val < 0) { 148 update(x, x, -val); 149 cout << -val << 'n'; 150 } else { 151 update(x, x, s); 152 cout << s << 'n'; 153 } 154 } 155 } source code 마찬가지.
  • 36. Lazy Propagation Not on Segment Trees Sogang ICPC Team 35 Lazy propagation의 아이디어는 세그먼트 트리에 한정해서 쓰이지 않는다
  • 37. Pixel Triangles # 16572 Sogang ICPC Team 36 2, 000 × 2, 000 크기의 격자 판이 주어지며, 각 픽셀(칸)은 행과 열을 이용해서 위치가 표시된다. 가장 왼쪽 열이 1열, 가장 위쪽 행이 1행이다. 이 때 픽셀 삼각형의 정의는 다음과 같다. ✓ 픽셀 삼각형은 3개의 자연수 A, B, C 에 대해서 P (A, B, C)로 표현된다. ✓ P (A, B, C) = {(x, y) | A ≤ x, B ≤ y, 0 ≤ (x − A) + (y − B) ≤ C − 1} 격자 위의 픽셀들로 구성된 픽셀 삼각형이 n ≤ 4, 000, 000개 주어졌을 때, 픽셀 삼각형들이 덮는 픽셀의 개수를 출력해라.
  • 38. Pixel Triangles # 16572 Sogang ICPC Team 37 P (1, 2, 3) = {(x, y) | 1 ≤ x, 2 ≤ y, 0 ≤ (x − 1) + (y − 2) ≤ 3 − 1}
  • 39. Pixel Triangles # 16572 Sogang ICPC Team 38 P (3, 1, 2) = {(x, y) | 3 ≤ x, 1 ≤ y, 0 ≤ (x − 3) + (y − 1) ≤ 2 − 1}
  • 40. Pixel Triangles # 16572 Sogang ICPC Team 39 P (5, 5, 1) = {(x, y) | 5 ≤ x, 5 ≤ y, 0 ≤ (x − 5) + (y − 5) ≤ 1 − 1}
  • 41. Pixel Triangles # 16572 Sogang ICPC Team 40 이 때 최종적으로 덮어지는 픽셀의 개수는 9개가 된다
  • 42. Pixel Triangles # 16572 Sogang ICPC Team 41 최악의 경우? ✓ P (0, 0, 2000)이 4, 000, 000개 있음 ✓ bool 배열에 나이브하게 채워넣는다면 배열 액세스 횟수 4, 000, 000 × 2, 000 (2, 000 + 1) 2 Lazy propagation의 아이디어를 어떻게 적용할 수 있을까?
  • 43. Pixel Triangles # 16572 Sogang ICPC Team 42 삼각형의 왼쪽 위 꼭짓점에 삼각형의 크기를 미리 적어두자 0 3 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1
  • 44. Pixel Triangles # 16572 Sogang ICPC Team 43 모든 픽셀을 왼쪽 오른쪽, 위 아래 순서대로 보면서, 지금 확인하고 있는 칸 ≥ 2라면 오른쪽 칸과 아랫쪽 칸을 갱신 0 3 2 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1
  • 45. Pixel Triangles # 16572 Sogang ICPC Team 44 삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다 0 3 2 1 0 0 2 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1
  • 46. Pixel Triangles # 16572 Sogang ICPC Team 45 삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다 0 3 2 1 0 0 2 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1
  • 47. Pixel Triangles # 16572 Sogang ICPC Team 46 삼각형 정보들만 적어두고 맨 마지막에만 전부 펼친(?)다 0 3 2 1 0 0 2 1 0 0 2 1 0 0 0 1 0 0 0 0 0 0 0 0 1
  • 48. Pixel Triangles # 16572 Sogang ICPC Team 47 작업이 끝나면 1 이상이 적힌 칸의 수는 9개! 0 3 2 1 0 0 2 1 0 0 2 1 0 0 0 1 0 0 0 0 0 0 0 0 1 소스는 생략
  • 49. 1회차 연습문제 Sogang ICPC Team 48 ✓ 구간 합 구하기 2 # 10999 ✓ JuQueen # 10277 ✓ Pixel Triangles # 16572 1. 스위치 # 1395 2. XOR # 12844 3. 하늘에서 떨어지는 1, 2, · · · , R − L + 1개의 별 # 17353 4. 수열과 쿼리 13 # 13925 5. Range GCD # 12858