본문 바로가기
PS/BOJ

백준 22878 / C++

by jaehoonChoi 2022. 9. 1.

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

 

22878번: 간단한 문제

길이가 $N$인 두 수열 $(p_1, p_2, \ldots, p_N)$, $(q_1, q_2, \dots, q_N)$ 이 주어진다. 이때 다음 값을 구하여라. $$\sum_{i=1}^{N} {\sum_{j=1}^{N} {\min(|p_i - p_j|, |q_i - q_j|)} }$$

www.acmicpc.net

 

[ 풀이 ] 

수학문제입니다. 두가지 잘 알려진 식을 이용합니다.

1. max(a, b)+min(a, b)=a+b

2. max(|a|, |b|)= abs((a+b)/2)+abs((a-b)/2) 

2번 식은 수직선에서 중점을 잡고 오른쪽 반 칸이 최댓값이므로 쉽게 증명됩니다. 

두 식을 이용하면, 식이 pi-pj 꼴 , qi-qj 꼴, (pi-qi)-(qi-qj)꼴 (pi+qi)-(pj+qj) 꼴 4가지가 나옵니다.

1가지는 대표적으로 구해봅시다. 

시그마 2개를 풀면 i=j 경우와 i<j, i>j 인 모든 1<=i,j<=N 쌍의 차이를 더한 것입니다.

i=j일땐 0이 되고, i<j와 i>j인 경우는 대칭성으로 같습니다. 

따라서 sigma(i<j) |pi-pj|를 구해서 2배해주면 됩니다. 저 합은 pi를 정렬한 후 O(n)에 구할 수 있습니다.

i<j인 모든 쌍의 차이는 정렬하고 구하든 그냥 구하든 모든 경우를 더하게 되므로 값이 일정합니다. 

이렇게 3번 더 해주면 됩니다. 차와 합 꼴은 2로 나누는 점에 유의합시다. 시간복잡도는 O(4NlogN)입니다. 

 

[ Code ] 

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAX = 1000010;
ll n, p[MAX], q[MAX], r[MAX], s[MAX];

int main() {
    cin.tie(0)->sync_with_stdio(0);
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i];
    for (int i = 0; i < n; i++) cin >> q[i]; 
    for (int i = 0; i < n; i++) {
        r[i] = p[i] - q[i];
        s[i] = p[i] + q[i];
    }
    sort(p, p + n); sort(q, q + n);
    sort(r, r + n); sort(s, s + n);
    ll ans = 0;
    for (ll i = 0; i < n; i++) {
        ans += 2 * (2 * i - n + 1) * (p[i] + q[i]);
        ans -= (2 * i - n + 1) * (r[i] + s[i]);
    }
    cout << ans << '\n';
}

 

 

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

BOJ 26092  (0) 2022.12.25
2022 충남대학교 SW-IT Contest - Division 1 풀이  (0) 2022.10.09
백준 16726 / C++  (0) 2022.08.31
백준 23878 / C++  (0) 2022.08.23
백준 23877 / C++  (0) 2022.08.23

댓글