There are many algorithms for reverse order pairs. Here we will talk about the idea of Reverse Order pairs for line segment trees.
Knowledge Point: Line Segment tree, reverse order pair, single point update, CIDR sum
Algorithm: the precondition for the line segment tree to calculate the number of reverse orders is to discretization and change to a continuous point. First, build a tree, and set each node to a num value of 0.
Then, according to the definition of the reverse order, the sum of the numbers shown above is larger than the current number. We need to ask the preceding number to be larger than the current number, in fact, it is equivalent to summing up all the numbers that have appeared after the current A [I] Point. Then, the value of the current vertex is changed to 1 on the leaf node of the Line Segment tree, indicating that it has appeared and is updated to the line segment tree. Example 4 2 1 5 3
First, there is no value after 4, and 4 is updated to 1, 4 -- 5 is updated to 1, 1 -- 5 is updated to 1,
Then 2, calculate the sum of the 3--5 range and update 2 to -- 2 to --- 5 to 2.
Then 1, calculate the 2--5 range and 2, and then update 1 to -- 2 to --- 5 to 3.
Then, 5, calculate the 5---5 range and 0, and then update the 5 range to -- 5 to -- 5 to 4.
Then 3, calculate the 4--5 range and 2.
Then add all the sums 1 + 2 + 2 = 5, that is, the number of Reverse Order pairs, the simplest line segment tree application.
For the current question, the array is required to be circular. You can start from any point and find a minimum number of reverse orders.
So we consider moving the current element to the end, which is equivalent to the number of reverse orders obtained last time minus the element a [I]-1 smaller than it, then add the element N-A [I]-1 that is larger than him, so you can obtain a minimum value through enumeration.
Code:
# Include <cstdio> # include <cstring> # include <algorithm> using namespace STD; const int n = 101000; int A [n]; struct node {int L, R, num ;}; node tree [4 * n]; void build (int l, int R, int o) {tree [O]. L = L, tree [O]. R = r; tree [O]. num = 0; If (L = r) return; int mid = (L + r)> 1; build (L, mid, O <1 ); build (Mid + 1, R, O + 1);} void Update (int t, int o) {If (tree [O]. L = tree [O]. R & tree [O]. L = T) {tree [O]. num ++; return;} int mid = (tr EE [O]. L + tree [O]. r)> 1; if (T> mid) Update (T, O + 1); else Update (T, O + O); tree [O]. num = tree [O + O]. num + tree [O + 1]. num;} int query (int l, int R, int o) {If (tree [O]. L = L & tree [O]. R = r) {return tree [O]. num;} int mid = (tree [O]. L + tree [O]. r)> 1; if (r <= mid) return query (L, R, O + O); else if (L> mid) return query (L, R, O + 1); else return query (L, mid, O * 2) + query (Mid + 1, R, O * 2 + 1);} int main () {// freopen ("input.txt", "r", STD In); int N; while (~ Scanf ("% d", & N) {for (INT I = 0; I <n; I ++) {scanf ("% d ", & A [I]); A [I] ++;} build (1, n, 1); int ans = 0; For (INT I = 0; I <N; I ++) {ans + = query (A [I], n, 1); Update (A [I], 1) ;}int sum = ans; for (INT I = 0; I <n; I ++) {sum + = n-A [I]-A [I] + 1; // printf ("% d \ n", sum); ans = min (ANS, sum);} printf ("% d \ n", ANS );} return 0 ;}