原来求逆序数还可以用线段树,涨姿势了。

首先求出原始序列的逆序数,然后递推每一个序列的逆序数。

 

 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 }
线段树

相关文章: