参考:http://blog.sina.com.cn/s/blog_691ce2b70101ldmm.html
https://blog.csdn.net/wiking__acm/article/details/7920429
语法:https://zhidao.baidu.com/question/172532047.html
1 #include <stdio.h> 2 #include <algorithm> 3 4 using namespace std; 5 6 int a[5005]; 7 struct Node{ 8 int l,r,num;//num该区间已出现数的个数 9 }tree[50000]; 10 11 void Build(int n,int x,int y){ 12 tree[n].l = x; 13 tree[n].r = y; 14 tree[n].num = 0; 15 if(x == y){ 16 return; 17 } 18 int mid = (x + y) / 2; 19 Build(2*n,x,mid); 20 Build(2*n+1,mid+1,y); 21 } 22 23 void Modify(int n,int x){//在输入的相应叶节点加1 24 int l = tree[n].l; 25 int r = tree[n].r; 26 int mid = (l + r) / 2; 27 if(x == l && x == r){ 28 tree[n].num = 1; 29 return; 30 } 31 if(x <= mid) Modify(2*n,x); 32 else Modify(2*n+1,x); 33 tree[n].num = tree[2*n].num + tree[2*n+1].num; 34 } 35 36 int Query(int n,int x,int y){//求大于该数且已经出现的数个数,n节点序号,x左端点,y右端点 37 int l = tree[n].l; 38 int r = tree[n].r; 39 int mid = (l + r) / 2; 40 int ans = 0; 41 if(x == l && y == r) 42 return tree[n].num; 43 if(x <= mid) ans += Query(2*n,x,min(mid,y)); 44 if(y > mid) ans += Query(2*n+1,max(mid+1,x),y); 45 return ans; 46 } 47 int main(){ 48 int n,sum,ans; 49 int i,j; 50 51 while(scanf("%d",&n) != EOF){ 52 sum = 0; 53 Build(1,0,n-1);//区间端点取0~n-1即可 54 for(i = 1;i <= n;i++){ 55 scanf("%d",&a[i]); 56 Modify(1,a[i]); 57 sum += Query(1,a[i]+1,n-1); 58 } 59 ans = sum; 60 for(i = 1;i < n;i++){ 61 sum = sum + (n - 1 - a[i]) - a[i];//根据递推式加上接下来依次循环的序列的逆序数 62 if(sum < ans) 63 ans = sum;//要最小的 64 } 65 printf("%d ",ans); 66 } 67 }