Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
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
29 30
Tags
more
Archives
Today
Total
관리 메뉴

lmlmlm

Educational Codeforces Round 131 (Rated for Div. 2) 본문

문제풀기

Educational Codeforces Round 131 (Rated for Div. 2)

lml 2022. 7. 9. 22:41

https://codeforces.com/contest/1701

 

F가 segtree하나 기똥차게 짜면 바로 풀렸을텐데 흠...

 

A. Grass Field

 

보면서 어지간히 낼게 없나 싶었다.

2번이 반드시 필요한지 확인해주면 된다.

 

B. Permutation

 

직관적으로 d = 2일 때가 최선

i, 2i, 4i ... 형태가 되도록 최선을 다해서 배열해주면 된다.

 

C. Schedule Management

 

이분탐색으로 시간을 구할 수 있다.

다만 최대시간이 2m이라는 점에만 유의를 하면 될 것 같다.

 

D. Permutation Restoration

 

각 b[i] 값당 가능한 a[i]의 범위가 [s, e]로 생겨난다.

e로 이들을 정렬하고 배정해줄 수 있는 남은 숫자들의 upper_bound(s)를 배정해주면 된다. (greedy)

pair<int, int>로 정렬을 했지만 생각해보니 결국 a의 값이 정수이기에 대충 나눠도 됐을 것 같다.

 

E. Text Editior

 

당연하게도 end 버튼을 누르는 것은 항상 손해이다.

또한 Home 버튼도 두 번 이상 누르면 손해이다. 

따라서 (맨 뒤) -> (어떤 지점 j) -> home -> (어떤 지점 i)의 방식으로 움직이는 것이 최선이다.

(단, 어떤 지점 i가 0이라면 home 버튼을 누를 필요가 없음에 주의하자.)

만일 저런 행동을 한다면 i부터 j까지는 T와 정확하게 매칭되어야 한다.

1) z function을 알고 있다면 매우 쉽게 할 수 있다. 

2) 굳이 z를 모르더라도 단순한 dp를 통해서 할 수 있다. (공간적인 면에서만 손해를 볼 뿐, 시간복잡도는 같다)

 

F. Points

 

어떤 숫자 a가 삽입될 때 더 생겨나거나 사라지는 triplet의 개수를 세보자.

[a - d, a)에 있는 어떤 숫자 i를 고르자.

이때 [i + 1, i + d] - {a} 에서 임의의 한 숫자 j를 고른다면 (i, a, j) 혹은 (i, j, a)가 생겨남을 알 수 있다.

따라서 sum( [i +1, i + d] - 1) 만큼의 triplet이 a보다 왼쪽에서 생겨난다.

정확히 a가 제일 왼쪽인 triplet의 개수는 [a + 1, a + d]의 원소의 수가 x라면 C(x, 2) 임을 알 수 있다.

-> 따라서 임의의 위치 i에 대해 [i + 1, i + d]에 있는 원소의 수를 관리해주는 자료구조를 만들어주면 된다.

하지만 유의해야하는 것은  sum([i + 1, i + d])에 포함되는 i는 set에 포함된 숫자여야 한다는 것이다.

 

따라서 다음과 같은 segtree를 만들어주면 된다. (물론 다음의 역할을 대체할 수 있는 방식을 채택해도 된다.)

sum(a[i] * b[i])의 출력이 가능하며, a의 구간갱신이 가능하고, b의 점갱신이 가능하다.

lazy를 이용하면 b의 구간갱신까지 가능하도록 설계해줄 수 있다.

https://codeforces.com/contest/1701/submission/163404022

따라서 쿼리마다 새롭게 생겨나거나 사라지는 triple의 개수를 세주면 된다.

 

Editorial) 

 

비슷하게 f(i) = [i + 1, i + d]에 있는 원소의 개수라고 정의한다면, 답은 sum(C(f(i), 2))이다.

-> 따라서 sum(f(i)^2)와 sum(f(i))를 관리할 수 있는 segtree를 만들어주면 된다.

여기서 질문) 그러면 f(i)의 구간갱신을 어떻게 할 수 있는가?

sum((f(i) + 1)^2) = sum(f(i)^2 + 2 * f(i) + 1)이기 때문에 sum(f(i)^2), sum(f(i))를 알고 있다면 쉽게 구할 수 있다.

-> 따라서 matrix를 곱해주는 형태의 segtree를 만들어주면 된다.

'문제풀기' 카테고리의 다른 글

Codeforces Round #810  (0) 2022.07.25
Codeforces Round #808 (Div. 1)  (0) 2022.07.18
Codeforces Round #803 (Div. 2)  (0) 2022.07.01
Codeforces Round #794 (Div. 1)  (0) 2022.06.06
Codeforces Round #796 (Div. 1)  (0) 2022.06.06
Comments