题意:给定一个序列,求出这个序列和它的循环序列里面逆序对的最小值

解题思路:线段树,这里建树不应该用数组来建树,而是建一个空树,然后边插入,变查找,类似于一个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\n",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\n",TMIN);
102      }
103      return 0 ;
104 }
View Code

 

posted on 2013-07-29 15:46  dark_dream  阅读(183)  评论(0编辑  收藏  举报