Reverse order to
For a sequence of \ (a_1...a_n\), define an ordered pair \ ((i,j) \) when and only if \ (i<j\) and \ (a_i>a_j\) are in reverse order. Then we'll think about how to ask.
* *. Merge sort
Review the process of merging and sorting, dividing the number of columns ([l,r]\) into two equal-length parts ([l,mid]\) and \ ([mid+1,r]\), sorting them down, and the cost of each merger being the length of the interval, So get the time complexity of:
\[t (n) =2t (\frac{n}{2}) +o (n) \]
According to the \ (master\) theorem, it is known that the time complexity is \ (\theta (nlog_2n) \)
int MergeSort (int l, int r) { if (l == r) return ; int mid = (l + r) >> 1; MergeSort(l, mid), MergeSort(mid + 1, r); int i = l, j = mid + 1, t = l; while(i <= mid && j <= r) if (a[i] <= a[j]) b[t++] = a[i++]; else b[t++] = a[j++]; while(i <= mid) b[t++] = a[i++]; while(j <= r) b[t++] = a[j++]; for(int k = l; k <= r; ++k) a[k] = b[k];}
Wait a minute! You have been talking so long, in the end how to seek reverse order???
We intercept a piece of code:
else b[t++] = a[j++]
Since the merge sort is to divide an interval into the left and right sides, so any element on the left side must be in any of the elements of a given paragraph, this property is also used for the division treatment, so when we add a right interval element, then the left part of the remaining element must be larger than it, so rewrite:
else b[t++] = a[j++], ans += mid - i + 1;//ans为逆序对个数
Because of the nature of the division, so every reverse order will not be heavy and not to be missed.
* *. Tree-like array
\ (bit\) as a clever data structure that exploits a prefix-like idea. The inverse pair is solved by the weighted value \ (bit\) .
The core of the algorithm is to establish the size relationship of \ (a_j<a_i\) , to insert its subscript from small to large, by calculating the prefix and the way to solve.
For example, we now have a number \ (a_i\), and we insert its subscript \ (i\) into \ (bit\ ) to calculate the number of current less than or equal to its subscript ( tot\), then the answer is \ (i-tot\).
Because \ ( a_i>a_j\) (\ (j\) is the subscript of the number previously inserted), the number of \ (i-tot\) is the position after \ (i\) is the current ( i\) contribution to the answer (satisfying \ (a_j<a_i\&j>i\)).
#include <cstdio>#include <algorithm>typedef long long ll;using std::sort;const ll N = 5e5 + 10;ll n, a[N], b[N], c[N], ans;inline bool cmp (ll x, ll y) { return a[x] < a[y] || (a[x] == a[y] && x < y); }inline ll lowbit (ll x) { return x & (-x); }inline void add (ll x, ll y) { for (; x <= n; x += lowbit(x)) c[x] += y; }inline ll query (ll x) { ll y = 0; for (; x > 0; x -= lowbit(x)) y += c[x]; return y; }int main () { scanf ("%lld", &n); for (ll i = 1; i <= n; ++i) scanf ("%lld", a + i), b[i] = i; sort (b + 1, b + n + 1, cmp); for (ll i = 1; i <= n; ++i) add(b[i], 1). ans += i - query (b[i]); printf ("%lld\n", ans);
Two methods of reverse order (review)