먼저 모든 lazy propagation 문제를 펜윅트리로 풀 수 있는 것은 아니다. 하지만 lazy propagation 문제 중 대표적인 유형 몇 개는 놀랍게도 펜윅으로 풀 수 있다. 여기서는 두 문제를 소개하려고 한다. 이 놀라운 방법은 다음 두 곳에서 설명하는 것으로 이해했다. www.acmicpc.net/blog/view/88 tony9402 님의 boj10999 풀이 먼저 대표적인 유형 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는 구간의 합을 구하는 횟수이다. 그리고 둘..

dp를 연습하기 위해 https://atcoder.jp/contests/dp/tasks 셋을 풀었다. 대부분의 문제가 유명하고, 문제 지문도 매우 직관적인 것으로 보아 꽤 정형화 된 문제들이라서 공부하기에 추천한다. 난이도 순은 아니라는데 맨 뒤의 문제가 체감상 더 어려웠다. 이번 글에서는 내가 스스로 못풀고 풀이(http://www.secmem.org/blog/2019/05/15/Education-Dp-Contest-Solution/)를 본 문제를 복습하는 의미로 정리하였다 T - Permutation dp[i][j] : 맨 앞 i개의 숫자를 1~i 숫자로 채워넣을 때 마지막 수가 j가 되도록하는 가짓수 sum[i][j] : 구간 합 배열로 dp[i][1] ~ dp[i][j] 의 합 $i..
https://www.acmicpc.net/problem/10742 해답을 보고 알았지만 재밌는 이분탐색 문제이다. 평균이 가능한 범위는 1부터 1000000까지 이다. 이분탐색으로 답이 p이상이 가능한지 확인하면서 범위를 좁히는 형식으로 해결할 수 있다. 답이 p이상이 가능한지 안한지 확인하는 방법은.. 먼저 각 요소에 p를 뺀 배열을 새롭게 만든다. 이때 만약, 길이가 k이상인 부분합이 0이상인 구간이 존재한다면 okay이다. 따라서 하나씩 index를 증가시키면서 미리 계산한 구간합배열 psum 을 두고 psum[index]≥mini≤index−k(psum[i]) 인 곳이 있는지 min(psum[i])를 update해주면서 확인하면 된다. using na..
boj 15977 이 문제의 해결 방법에 대한 아이디어 및 코드 출처(koosaga님), 설명은 2020/01/24 - [분류 전체보기] - dp와 분할정복으로 LIS 해결 에서 충분히 하였다. 본 문제를 다시 설명하면 m=2일 때는 첫 째 행에 대해 정렬시켰을 때 두 번째 행에 대한 lis를 구하는 문제이므로 간단하다. m=3일 때가 중요한데... 마찬가지로 같은 아이디어를 적용하면 첫 째 행에 대해 정렬시켰을 때 pair에 대한 lis를 구하는 문제로 바뀐다. 그리고 이 문제에 대한 핵심 아이디어 dp와 divide&conquer 풀이법은 이전글에서 설명하였다. 항이 하나 늘어나기는 했으나 핵심은 같다. 단, 원소의 범위가 1~109 이므로 좌표 압축을 해야 한다. 따라서 코드로 설명..

LIS(Longest Increasing Subsequence)를 해결하는 방법은 다양하다. 특히 O(nlogn) 으로 푸는 방법들에는 이분탐색과 세그먼트 등이 있다. 이번에는 시간복잡도는 O(nlog2n) 으로 약간 뒤쳐지지만 분할정복과 dp로 lis의 길이를 구할 수 있는 방법에 대해 써보려고 한다. 이 풀이는 KOI 2018 고등부 3번 조화로운 행렬 을 풀어보려고 하다가 ba*arkingdog님의 블로그를 보고 알게된 koosaga님의 댓글을 보고 알게 되었다. (복잡한 사연..) https://codeforces.com/blog/entry/43319 여기를 보면 이와 같이 풀이에 대한 아이디어가 적혀있는데 여기서 붉은 문단을 이해할 수 없어서 결국 koosaga님의 조화로운 행렬풀이를 ..

boj 10548 solved.ac 기준 platinum 5 문제이다. 하지만 이런 문제 유형을 처음 본 나로서는 정말 어려웠다.. COCI 공식 해답지를 보고 공부한 결과, 문제의 아이디어는 히스토그램의 최대 넓이를 구하는 문제를 스택을 사용한 스위핑 알고리즘으로 푸는 것과 비슷하다. (BOJ 1725) 히스토그램 문제를 분할 정복으로 해결하면 O(NlogN) 이 걸리지만 스위핑 알고리즘으로는 O(N) 으로 충분하다. 마찬가지로 이번 문제도 O(NM) 의 시간복잡도로 해결가능하다. 본 문제를 해결하는 기본 방법은 직사각형의 오른쪽 아래점을 고정 시켰을 때 몇 가지의 직사각형이 나올 수 있는지 구해서 모두 더하는 것이다. i행에 대해서 위의 스위핑 알고리즘이 어떻게 적용되는지 알아보자. $..
boj 14459 아무리 생각해도 dp로 푸는 시간 복잡도 O(N2), 공간복잡도도 N2 인 풀이밖에 생각이 나지 않았다. 따라서 답지를 봤는데... 자바 언어로 되어 있어서 해석하기 힘들었다. 그리고 처음에 lattice point를 어떻게 잡는다는 것인지도 헷갈렸다. 꽤 오랜 시간을 쓰고 나서 이해했고 직관적인 꽤 간단한 풀이가 있음을 알 수 있었다. 먼저 목초지가 왼쪽과 오른쪽으로 나눠져 있다. 밑의 코드를 참고하면 쉽게 이해할 수 있을테지만 문자 정의부터 내리겠다. a[i] : 왼쪽 목초지의 i번째 종류 s[i] : 오른쪽 목초지에서 종류 i 목초지의 위치 (단, index는 0부터 n−1이다.) 그리고 dp와 segment tree를 이용할 것이다. 구간 $[..
ax+by=c 의 해를 찾는 방법 먼저 c가 gcd(a,b)의 배수가 되어야 한다. 만약 gcd(a,b)의 배수가 아니라면 좌변은 gcd(a,b)로 나누어 떨어지지만 우변은 안 나눠떨어지기 때문에 모순이다. 따라서 우리는 ax+by=gcd(a,b) 의 해를 구할 것이다. 그리고 한가지 짚고 넘어가야 하는 점은 ax+by의 꼴은 항상 gcd(a,b)의 배수이다. a=bq+r(단,b>r≥0) 라 하자 주어진 식에 a값을 대체 하면 (bq+r)x+by=gcd(bq+r,b) 이 되고 정리하면 b(qx+y)+rx=gcd(r,b) 이 된다. 가운데 정렬한 두 식을 비교하자. 만약 아래식 bx′+ry′=gcd(b,r)의 해를 (x′,y′)를 구..