先吐槽
这题做了两天,昨天讲分治,老师用归并讲了一遍,今天又用树状数组讲了一遍
归并不难,啊啊啊我居然才调出来
思路
归并两个数组时,对于第二个数组的元素a[c2],它与第一个数组中目前还没归到总数组里的元素形成逆序对
c1,c2是指针,对于a[c2],它与a[c1..mid]构成逆序对,贡献{mid - c1 + 1}对
注意
ans开longlong,不然会WA一半!
临时数组c开成全局变量,函数里放不下
两种记录方式
>函数不返回值,ans开成全局变量,在每次归并两个数组时增加对数
>函数返回值,ans开在函数里,赋值递归两个分数组的返回值之和,再加上归并两个数组时的对数
#include <iostream> #include <algorithm> #include <cstdio> #include <string> #include <cstring> #include <cmath> using namespace std; long long n , ans; int a[500005] , c[500010]; long long back(int l , int r) { if(l == r) return 0; int mid = l + (r - l) / 2; long long ans = back(l , mid); ans += back(mid + 1 , r); int c1 = l , c2 = mid + 1 , top = l;//c[500010]太大,只能开全局 while (c1 <= mid && c2 <= r) { if(a[c1] <= a[c2]) c[top++] = a[c1++]; else { c[top++] = a[c2++]; ans += mid - c1 + 1; } } while (c1 <= mid) c[top++] = a[c1++]; while (c2 <= r) c[top++] = a[c2++]; for (int i = l ; i <= r ; i++) a[i] = c[i]; return ans; } int main() { cin >> n; for (int i = 1 ; i <= n ; i++) { cin >> a[i]; } ans = back(1 , n); cout << ans << endl; return 0; }