版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/82930224
题目链接:https://vjudge.net/problem/Aizu-ALDS1_5_D
思路:(挑战程序设计(算法与数据结构))
需要特别注意的有两点:1 在Left和Right数组中的末尾要加一个INF,保证其中一个数组为空时,另一个数组能继续把数填进A数组中;2 二分中 L和R的取值;
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int Maxn = 2e5+10;
int a[Maxn],Left[Maxn/2],Right[Maxn/2];
ll merge (int A[], int mid, int L, int R);
ll solve (int A[], int L, int R) {
int mid; ll ans1,ans2,ans3;
if (L < R) {
mid = (L+R)/2;
ans1 = solve (A, L, mid);
ans2 = solve (A, mid+1, R);
ans3 = merge (A, mid, L, R);
return ans1+ans2+ans3;
} else return 0;
}
ll merge (int A[], int mid, int L, int R) {
int n1 = mid-L+1;
int n2 = R-(mid+1)+1;
for (int i = 0; i < n1; ++i) Left[i] = A[L+i];
for (int i = 0; i < n2; ++i) Right[i] = A[mid+1+i];
Left[n1] = Right[n2] = 1e9+10; // 当有左右的数组中的有意义的数为空时,要保证最后一个数比另一个数组所有的数都大,
ll ans = 0; // 才能保证把所有的数都放进A数组中
int i, j; i = j = 0;
while (L <= R) {
if(Left[i] <= Right[j]) {
A[L++] = Left[i++];
} else {
ans+=n1-i;
A[L++] = Right[j++];
}
}
return ans;
}
int main (void)
{
int n;
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
ll ans = solve (a, 0, n-1);
cout << ans << endl;
return 0;
}