※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1637번 문제인 날카로운 눈이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1637
1637번: 날카로운 눈
첫째 줄에 입력의 개수 N이 주어진다. N은 1이상 20,000이하인 수이다. 그 다음 줄부터 N줄에 걸쳐 세 개의 정수 A, C, B가 주어지는데, 이것은 A, A+B, A+2B, ..., A+kB (단, A+kB ≦ C) 의 정수들이 정수더미
www.acmicpc.net
주어지는 정수들 중 홀수번 등장하는 수 ans가 유일하게 주어진다는 점에 주목하자.
홀수번 등장하는 수는 ans가 유일하므로, ans보다 작은 양의 정수 x에 대하여 [1,x]에 포함된 정수의 개수는 항상 짝수개이고 ans 이상의 양의 정수 y에 대하여 [1,y]에 포함된 정수의 개수는 항상 홀수개라는 것을 알 수 있다.
위의 성질을 이용하면 O(N)의 시간복잡도로 mid 이하의 정수의 개수를 세는 것을 반복하여 이분탐색으로 문제를 해결할 수 있다. 총 시간복잡도는 O(NlgMAX)이다. (N은 주어지는 정수더미의 개수, MAX는 이분탐색 범위 최댓값)
아래는 제출한 소스코드이다.
#include <iostream>
using namespace std;
typedef long long ll;
int N;
ll A[20000];
ll B[20000];
ll C[20000];
ll func(ll mx) {
ll ret = 0;
for (int i = 0; i < N; i++) {
ll L = A[i], R = min(C[i], mx), K = B[i];
if (L <= R) ret += (R - L) / K + 1;
}
return ret;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for (int i = 0; i < N; i++) {
cin >> A[i] >> C[i] >> B[i];
}
ll L = 1, R = 2147483648;
while (L < R) {
ll mid = (L + R) / 2;
ll midcnt = func(mid);
if (midcnt & 1) R = mid;
else L = mid + 1;
}
if (L == 2147483648) cout << "NOTHING";
else cout << L << ' ' << func(L) - func(L - 1);
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 14499 // C++] 주사위 굴리기 (0) | 2022.07.10 |
---|---|
[BOJ 17773 // C++] Fortune Telling (0) | 2022.07.09 |
[BOJ 1646 // C++] 피이보나치 트리 (0) | 2022.07.07 |
[BOJ 2041 // C++] 숫자채우기 (0) | 2022.07.06 |
[BOJ 11058 // C++] 크리보드 (0) | 2022.07.05 |