믿을 수 없을만큼 짤막한 답안 코드를 보고도 이해하는데 오랜시간이 걸렸으며
이런문제를 100개쯤 가져다 주고 99개를 답보고 푼다 해도 마지막 한문제조차 스스로 풀 자신이 없기에
너무도 화가난 나머지 블로그에 이 문제를 이해한 방식을 적는다
원소의 수는 20만개 -> 시간초과에 유의해야 함
원소는 양수 뿐만이 아니라 음수와 0이 포함됨 -> 일반적으로 풀 문제는 아님
결국 정확히 평균이 K가 나오는 구간을 하나하나 세는 문제가 아니라 기발하고 참신한 풀이법을 이용하여 정답만 가져가야 하는 불합리한 문제라는 것을 알 수 있다.
#define ll long long int
using namespace std;
ll n, k;
map<ll, ll> mp;
ll sum = 0;
ll tmp;
ll cnt = 0;
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
ll a;
cin >> a;
sum += a;
tmp = sum - i * k;
cnt += mp[tmp]++;
}
cnt += mp[0];
cout << cnt << endl;
}
10억단위의 수가 20만개나 있으니 모두 더했을때 long long int로 감당이 되나 싶었는데 일단 되는 모양이다.
sum으로 누적합을 구하나, 모든 구간의 누적합을 구해야 하기 때문에 진짜 모든 구간을 구했다가는 20만x20만으로 시간초과가 날 것이다.
그래서 tmp라는 오차의 개념이 등장했다.
sum은 i개의 원소의 합이고 원소가 i개일때의 바람직한 누적합은 i * k 일 것이다.
즉 sum이 바람직한 수가 되려면 (sum - i * k) 만큼이 필요하다는 것. (다시말해 (sum - i * k)가 0이라면 해당 구간의 평균이 K라는 뜻이다.)
이 오차의 횟수를 저장하는게 핵심이다
이부분이 죽어라고 이해가 안됐는데 어쨋든 내가 이해한 방식을 기록해두자면
mp[A]들은 전부 0 ~ i 까지의 누적합의 오차 A 의 갯수를 기록해둔 곳이다.
0~6 까지의 누적합의 오차가 5라면 mp[5] 에 1이 더해질 것이고
추후 0~10까지의 누적합의 오차가 5라면 mp[5]에 또 1이 더해질 것이다.
이것이 왜 즉시 정답을 저장하는 변수 cnt 에 더해지는가?
0~6과 0~10의 예를 들었다. 두 구간의 오차가 동일한 5 라면
(0~10) - (0~6)의 구간 (7~10)의 오차는 5 - 5 = 0일 것이며 오차가 0 즉, 평균 K라는 결과가 나온다
고로 같은 수의 오차가 2번이상 나오면 해당 구간 사이에 어떻게든 평균 K를 만들 수 있다는 뜻이므로 cnt에 수를 올려주는 것이다.
'백준' 카테고리의 다른 글
백준 1214번 쿨한 물건 구매 (c++) (0) | 2025.01.17 |
---|---|
백준 9202번 Boggle (c++) (0) | 2025.01.16 |
백준 2579번 문제- 계단 오르기 (0) | 2021.11.13 |
성적을 받아서 막대그래프 만들기 (0) | 2021.08.13 |
반복문으로 피보나치 다시짜봄 (0) | 2021.08.11 |