본문 바로가기
PS/BOJ

백준 25332 / C++

by jaehoonChoi 2022. 7. 7.

https://www.acmicpc.net/problem/25332

 

25332번: 수들의 합 8

$A = \{1, 2, 3\}$, $B = \{1, 3, 2\}$로, 조건을 만족하는 $i, j$ 쌍은 $(1, 1), (2, 3), (1, 3)$의 세 가지이다. $A_1$ = $B_1 = 1$ $A_2 + A_3 = B_2 + B_3 = 5$ $A_1 + A_2 + A_3 = B_1 + B_2 + B_3 = 6$

www.acmicpc.net

 

[ 풀이 ] 

 

B[i]-A[i]=C[i]라고 하자.  C[i]+...+C[j]=0 인 (i,j) 쌍을 구하자. 

C[i]까지 누적합을 pref[i]라 하면, pref[i-1]==pref[j]인 (i,j)를 구하면 된다. 

단순하게 O(N^2)에 구하면 TLE이다. 

값과 횟수를저장하는 배열 X를 만들어주면 쉽다. (X[값]=횟수) 

만약 지금 pref[i]의 값이 3이 나왔고, 다음에 X[pref[j]]가 0이 아니라면(즉, 이미 갱신된적 있다.)

값 X[pref[j]]는 지금까지 pref[i]=3이 나온 횟수가 된다. 따라서 j미만 모든 쌍을 셀 수 있다.

(i,j)를 센 이후엔 X[pref[j]]값을 1 더해주면 갱신된다. 

이러면 O(N)에 해결할 수 있다. 

그런데 문제는 pref[i]가 너무 커질 수 있다. C[i]는 최대 10^4이고,  N<=2e5이므로, 

pref는 2e9까지 나와서 배열에 담는건 불가능하다. 또한 pref값은 산발적이므로, 

모든 값 X[0]~X[2e9]를 알 필요는 없다. 이럴때 map을 써주면 된다. 

map은 그 value와 key만을 저장하므로 pref값이 커져도 가능하다.

 

[ 코드 ] 

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll A[200001], B[200001], pref[200001];
map<ll, ll> X;
#define for(i,n) for (int i=1;i<=n;i++)
 
int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n; cin >> n;
    for (i, n) cin >> A[i];
    for (i, n) cin >> B[i];
    // 누적합 만들기
    for (i, n) pref[i] = pref[i - 1] + B[i] - A[i];
    ll ans = 0;
    // pref[i-1]=pref[j]인 (i,j) 세기
    for (i, n) {
        if (pref[i] == 0) ans++; // i=1인 경우 pref[i]=0인걸 모두 세준다.(예외처리) 
        ans += X[pref[i]]++; // (... , i) 쌍 모두 세주고 갱신 
    }
    cout << ans << '\n';
}

 

 

 

'PS > BOJ' 카테고리의 다른 글

백준 1238 / C++  (0) 2022.07.13
백준 25339 / C++  (0) 2022.07.12
백준 1111 / C++  (0) 2022.07.09
백준 1007 / C++  (0) 2022.07.08
백준 1027 / C++  (0) 2022.07.07

댓글