티스토리 뷰
문제 설명이 이게 다인 문제 설명은 간단한 문제이다. 이 문제를 처음 볼 때 이상한 수학으로 풀어야 되는 건가 싶을 수 있지만 사실 세그를 사용해서 풀 수 있다. 일단 |p [i]-p [j]| 를 1번이라고 하고 |q [i]-q [j]| 를 2번이라고 하겠다.
이 문제는 1번과 2번 중 작은 값을 골라야 하기 때문에 1번이 작은 경우와 2번이 작은 경우 이렇게 2개로 나눌 수 있다.
1번이 작거나 같은 경우부터 생각해보자. 1번이 작거나 같을려면 (j < i)
p[i] >= p[j] 일때 | p[i] < p[j] 일때 |
p[i]-p[j] <= q[i]-q[j] | p[j]-p[i] <= q[i]-q[j] |
p[i]-p[j] <= q[j]-q[i] | p[j]-p[i] <= q[j]-q[i] |
이렇게 4가지의 경우가 생긴다. 이때 p를 정렬한다면 어떻게 될까? p를 정렬한다면 p [i] >= p [j]만 존재하게 된다. 그러므로 p [i] < p [j]는 없어져서 2가지 조건만 남게 된다. 이제 조금 더 나아가 보자.
p [i]-p [j] <= q [i]-q [j]라는 식을 적절히 이항 시켜주면 p [i]-q [i] <= p [j]-q [j]가 된다. 또 p [i]-p [j] <= q [j]-q [i] 도 이항 시켜주면 p [i]+q[i] <= p[j]+q[j] 가 된다. 이때 여기서 무언가 보인다는걸 알 수 있다. p[i] 와 q[i]는 i라는 같은 위치에 있는 것이고 p[j] 와 q[j] 도 맞찬가지다. 그러면 p를 정렬할 때 q는 처음에 입력받았을 때 같은 위치에 있는 p[i]와 이어준 다음 정렬을 해주게 되면 반복을 하면서 i번째가 되면 p[i], q[j] 모두 알게되는 것이다. 또 위에서 j가 더 작다고 했기 때문에 이미 i가 되기 전에 탐색을 한 것이다. i 번째에선 0 ~ i-1 위치랑 비교했을 때 p[i] - q[i]가 작은 것들을 찾으면 되기 때문에 j 번째 값을 빠르게 불러와 탐색을 할 수 있다면 이 문제를 풀 수 있게 되는것이다. 이때 세그를 사용하면 j번째 값들을 구할 수 있다.
일단 처음에 2개의 세그를 만들고 각각 세그에 개수를 저장하는 노드와 합을 저장하는 노드를 만들어 준다. p를 기준으로 정렬을 한 뒤 반복을 하면서 합 노드에 p [i] - q [i] 와 p[i] + q[i] 위치에 p[i] 를 더해준다. 그리고 같은 위치에 개수 노드에는 1을 더해준다. p[i]를 더해주는 이유는 조금 뒤에 알게 될 것이다.
값을 더해주는 코드 앞에 p [i] - q[i] 보다 같거나 큰 위치의 값을 모두 더해주는 코드를 작성해준다. 위에서 썼던거 처럼 p [i]-q [i] <= p [j]-q [j] 를 만족해야되고 위에서 p[j]-q[j] 위치에 p[j]를 더해주고 있으니 p[i]-q[i] 보다 같거나 큰 위치들에서의 합을 구해주게 되면 위 식을 만족하는 p[j]를 구할 수 있다. 이때 p[j]를 구해주는 이유는 |p [i]-p [j]|를 구해줘야되는 것이고 정렬을 해줬기 때문에 p[i] >= p[j]는 언제나 성립한다. 그러므로 |p[i]-p[j]| 이 값을 모두 더해줄때 |p[i]-p[j_1]|+|p[i]-p[j_2]|+|p[i]-p[j_3]| .... 이렇게 되는데 이 식을 풀어주면 p[i]*(p[j]의 개수)-(p[j]의 합) 이 된다. 그러므로 p[j]의 합과 개수를 구해주게 되면 p[i]-q[i] <= p[j]-q[j] 이 식을 만족하는 |p[i]-p[j]|를 구할 수 있다. 위와 같은 방법으로 p [i]+q [i]도 다른 세그에서 똑같은 방법으로 구해주는 것을 반복하면 1번이 작거나 같은 경우의 합을 구할 수 있게 된다.
이제 2번이 작은 경우를 구해줘야 되는데 이것도 위와 같은 방법으로 해주는데 이때는 같거나 작은 경우가 아닌 작은 경우만 구해줘야 되기 때문에 위와 같은 방법이지만 위치에 +1을 해준 다음 값을 구해주면 된다.
이렇게 값을 구해준 뒤 두 값을 더한 뒤 *2를 해주면 된다.(*2를 해주는 이유는 i와 j가 반대로 됐을 때도 절댓값이 쓰여있기 때문에 같은 값이 나오기 때문에 마지막에 *2를 해주는 것이다.)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct nd{
ll cnt,v;
};
vector<nd>t(8000020);
vector<nd>mt(8000020);
ll p[1000001],q[1000001];
pair<ll,ll>st[1000001];
void seg(ll n,ll s,ll e){
t[n]={0,0};
mt[n]={0,0};
if(s==e)return;
seg(n*2,s,(s+e)/2);
seg(n*2+1,(s+e)/2+1,e);
}
nd S(ll n,ll s,ll e,ll left,ll right){
if(left>e||right<s){return {0,0};}
if(left<=s&&e<=right){return t[n];}
nd Left=S(n*2,s,(s+e)/2,left,right);
nd Right=S(n*2+1,(s+e)/2+1,e,left,right);
return{Left.cnt+Right.cnt,Left.v+Right.v};
}
void c(ll n,ll s,ll e,ll i,ll f){
if(i<s||i>e){return;}
t[n].cnt++;
t[n].v+=f;
if(s!=e){c(n*2,s,(s+e)/2,i,f);c(n*2+1,(s+e)/2+1,e,i,f);}
}
nd ms(ll n,ll s,ll e,ll left,ll right){
if(left>e||right<s){return {0,0};}
if(left<=s&&e<=right){return mt[n];}
nd Left=ms(n*2,s,(s+e)/2,left,right);
nd Right=ms(n*2+1,(s+e)/2+1,e,left,right);
return{Left.cnt+Right.cnt,Left.v+Right.v};
}
void mc(ll n,ll s,ll e,ll i,ll f){
if(i<s||i>e){return;}
mt[n].v+=f;
mt[n].cnt++;
if(s!=e){mc(n*2,s,(s+e)/2,i,f);mc(n*2+1,(s+e)/2+1,e,i,f);}
}
int main()
{
ll a,ans1=0,ans2=0,C,V,P,Q,C1,V1;
nd T,T1;
scanf("%lld",&a);
for(int i=0;i<a;i++)scanf("%lld ",&p[i]);
for(int i=0;i<a;i++)scanf("%lld ",&q[i]);
for(int i=0;i<a;i++){st[i].first=p[i];st[i].second=q[i];}
sort(st,st+a);
seg(1,1,2000001);
for(int i=0;i<a;i++){
P=st[i].first;
Q=st[i].second;
T=S(1,1,2000001,P-Q+1000000,2000001);
C=T.cnt;
V=T.v;
T1=ms(1,1,2000001,P+Q,2000001);
C1=T1.cnt;
V1=T1.v;
ans1+=(C+C1)*P-V-V1;
c(1,1,2000001,P-Q+1000000,P);
mc(1,1,2000001,P+Q,P);
}
for(int i=0;i<a;i++){st[i].first=q[i];st[i].second=p[i];}
sort(st,st+a);
seg(1,1,2000001);
for(int i=0;i<a;i++){
Q=st[i].first;
P=st[i].second;
T=S(1,1,2000001,Q-P+1000001,2000001);
C=T.cnt;
V=T.v;
T1=ms(1,1,2000001,Q+P+1,2000001);
C1=T1.cnt;
V1=T1.v;
ans2+=(C+C1)*Q-V-V1;
c(1,1,2000001,Q-P+1000000,Q);
mc(1,1,2000001,Q+P,Q);
}
printf("%lld\n",(ans1+ans2)*2);
}
'ps' 카테고리의 다른 글
BOJ 25402(트리와 쿼리)풀이 (0) | 2022.09.09 |
---|---|
BOJ 12722(Mousetrap (Large))풀이 (0) | 2022.08.04 |
BOJ 22988(재활용 캠페인)풀이 (0) | 2022.01.23 |
BOJ 8872(빌라봉)풀이 (0) | 2022.01.14 |
BOJ 17163(가희의 수열놀이 (Large))풀이 (0) | 2022.01.06 |
- Total
- Today
- Yesterday
- 잡봇
- 수학
- 선분 교차 판정
- BOJ
- 깊이 우선 탐색
- 세그먼트 트리
- KOI
- 트리에서의 다이나믹 프로그래밍
- Python
- 최소 스패닝 트리
- codeforces
- 정렬
- 그래프 탐색
- 느리게 갱신되는 세그먼트 트리
- discord bot
- 누적 합
- 그리디 알고리즘
- 다이나믹 프로그래밍
- C++
- 완전 탐색
- 자료 구조
- 그래프 이론
- 자료구조
- 개발
- 알고리즘
- 이분 탐색
- 트리
- 이분매칭
- 구현
- A Dance of Fire and Ice
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |