题意:给定一个序列,求出这个序列和它的循环序列里面逆序对的最小值
解题思路:线段树,这里建树不应该用数组来建树,而是建一个空树,然后边插入,变查找,类似于一个hash树,快速找比它大的数字。循环队列的逆序对为可以dp得出
解题代码:
1 #include <stdio.h> 2 #include <string.h> 3 #define MAXN 5005 4 struct node 5 { 6 int left ,right,mid ; 7 int num; 8 }tree[4*MAXN]; 9 int L(int c) 10 { 11 return 2*c; 12 } 13 int R(int c) 14 { 15 return 2*c + 1; 16 } 17 void up(int c ) 18 { 19 tree[c].num = tree[L(c)].num + tree[R(c)].num; 20 } 21 int a[MAXN]; 22 void build(int c, int p , int v) 23 { 24 tree[c].left = p ; 25 tree[c].right = v ; 26 tree[c].mid = (p+v)/2; 27 tree[c].num = 0 ; 28 if(p == v ) 29 { 30 return ; 31 } 32 build(L(c),p,tree[c].mid); 33 build(R(c),tree[c].mid+1,v); 34 up(c); 35 } 36 int tsum = 0 ; 37 void F(int c , int p , int v ) 38 { 39 // printf("%d ",c); 40 /*if(p <= tree[c].left && v >= tree[c].right) 41 { 42 tsum += tree[c].num; 43 return ; 44 } 45 if(v <= tree[c].mid) F(L(c),p,v); 46 else if(p > tree[c].mid) F(R(c),p,v); 47 else 48 { 49 F(L(c),p,tree[c].mid); 50 F(R(c),tree[c].mid +1 , v ); 51 }*/ 52 if(p <= tree[c].left && v >= tree[c].right) 53 { 54 tsum += tree[c].num; 55 return ; 56 } 57 if(tree[c].mid < p ) F(R(c),p,v); 58 else if(tree[c].mid >= v) F(L(c),p,v); 59 else 60 { 61 F(L(c),p,tree[c].mid); 62 F(R(c),tree[c].mid+1,v); 63 } 64 } 65 void update(int c , int p) 66 { 67 if(tree[c].left == p && tree[c].right == p ) 68 { 69 tree[c].num = 1 ; 70 return ; 71 } 72 if(p <= tree[c].mid) update(L(c),p); 73 else update(R(c),p); 74 up(c); 75 } 76 int main() 77 { 78 int n ; 79 while(scanf("%d",&n)!= EOF) 80 { 81 memset(tree,0,sizeof(tree)); 82 build(1,1,n); 83 int sum = 0; 84 for(int i = 1;i <= n;i ++) 85 { 86 tsum = 0 ; 87 scanf("%d",&a[i]); 88 a[i] = a[i] + 1; 89 F(1,a[i],n); 90 sum += tsum; 91 update(1,a[i]); 92 } 93 94 int TMIN= sum; 95 for(int i = 1; i < n;i ++) 96 { 97 sum = sum - (a[i]- 1 ) + (n-a[i]); 98 if(sum < TMIN) 99 TMIN = sum; 100 } 101 printf("%d ",TMIN); 102 } 103 return 0 ; 104 }