原来求逆序数还可以用线段树,涨姿势了。
首先求出原始序列的逆序数,然后递推每一个序列的逆序数。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 20000 + 10; 7 8 int n, p, qL, qR; 9 int sum[maxn], a[5000 + 10]; 10 11 void update(int o, int L, int R) 12 { 13 if(L == R) { sum[o]++; return; } 14 int M = (L + R) / 2; 15 if(p <= M) update(o*2, L, M); 16 else update(o*2+1, M+1, R); 17 sum[o] = sum[o*2] + sum[o*2+1]; 18 } 19 20 int query(int o, int L, int R) 21 { 22 if(qL <= L && qR >= R) return sum[o]; 23 int ans = 0; 24 int M = (L + R) / 2; 25 if(qL <= M) ans += query(o*2, L, M); 26 if(qR > M) ans += query(o*2+1, M+1, R); 27 return ans; 28 } 29 30 int main() 31 { 32 //freopen("in.txt", "r", stdin); 33 34 while(scanf("%d", &n) == 1) 35 { 36 memset(sum, 0, sizeof(sum)); 37 38 for(int i = 0; i < n; i++) scanf("%d", &a[i]); 39 int inv = 0; 40 for(int i = 0; i < n; i++) 41 { 42 p = a[i]; 43 qL = a[i]; qR = n - 1; 44 inv += query(1, 0, n - 1); 45 update(1, 0, n - 1); 46 } 47 int ans = inv; 48 for(int i = 0; i < n; i++) 49 { 50 inv = inv + n - a[i]*2 - 1; 51 ans = min(ans, inv); 52 } 53 printf("%d\n", ans); 54 } 55 56 return 0; 57 }