首页 > 代码库 > HDU1394(Minimum Inversion Number)

HDU1394(Minimum Inversion Number)

题目地址:Minimum Inversion Number

 

题目大意:

    求逆序对数,求循环移位后逆序数的最小值,意思一次将第一位移到最后一位,然后计算逆序对数,求出最小的那个。

 

解题思路:

     因为是序列0->n-1区间的数,所以当你求的,它给出的a1.a2...an-1的逆序对数时cnt,推出如果移位后:设移位a[0],则移位后的逆序对数为 cnt-a[0]+(n-a[i]-1)。知道公式所以先求出给出序列的逆序对,然后从0->n-1移位求出最小的min数即可。

可以用:线段数、树状数组、和归并做。

线段数:开0->n-1的线段数,然后一次将给出a[i]添加到线段数中,然后计算a[i+1]时就可以对线段数中a[i+1]->n-1区间查找,计算在该区间已经有多少个数已经被添加完成,说明这个数出现在a[i+1]的前面(因为这个区间都大于a[i+1])。

 

代码:

  1 #include <algorithm>  2 #include <iostream>  3 #include <sstream>  4 #include <cstdlib>  5 #include <cstring>  6 #include <cstdio>  7 #include <string>  8 #include <bitset>  9 #include <vector> 10 #include <queue> 11 #include <stack> 12 #include <cmath> 13 #include <list> 14 //#include <map> 15 #include <set> 16 using namespace std; 17 /***************************************/ 18 #define ll long long 19 #define int64 __int64 20 #define PI 3.1415927 21 /***************************************/ 22 const int INF = 0x7f7f7f7f; 23 const double eps = 1e-8; 24 const double PIE=acos(-1.0); 25 const int d1x[]= {0,-1,0,1}; 26 const int d1y[]= {-1,0,1,0}; 27 const int d2x[]= {0,-1,0,1}; 28 const int d2y[]= {1,0,-1,0}; 29 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 30 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1}; 32 const int diry[]= {-2,-2,-1,-1,1,1,2,2}; 33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/ 34 /***************************************/ 35 void openfile() 36 { 37     freopen("data.in","rb",stdin); 38     freopen("data.out","wb",stdout); 39 } 40 priority_queue<int> qi1; 41 priority_queue<int, vector<int>, greater<int> >qi2; 42 /**********************华丽丽的分割线,以上为模板部分*****************/ 43 const int M=5010; 44 struct tree 45 { 46     int sum; 47     int left,right;  //记录区间的左右闭区间坐标 48 } node[M*4];  //需开四倍的空间大小 49 int p[M]; 50 int cnt; 51 void build__tree(int id,int l,int r)  //建树 52 { 53     int mid=(l+r)/2; 54     node[id].left=l;   //初始化赋值区间的坐标 55     node[id].right=r; 56     if (l==r) 57     { 58         node[id].sum=0;  //初始化区间节点的val值 59         return ; 60     } 61     build__tree(id*2,l,mid);  //左孩子 62     build__tree(id*2+1,mid+1,r); //右孩子 63     node[id].sum=node[id*2].sum+node[id*2+1].sum;  //通过递归将各个区间节点val更新 64 } 65 int sum(int id,int l,int r)  //区间的更新 66 { 67     int mid=(node[id].left+node[id].right)/2; 68     if (node[id].left==l&&node[id].right==r) 69         return node[id].sum; 70     if (l>mid)   //[l,r]在右孩子部分 71         return sum(id*2+1,l,r); 72     else if (r<=mid) // [l,r]在左孩子部分 73         return sum(id*2,l,r); 74     else  //[l,r]区间,左右孩子都有分别递归。 75         return sum(id*2,l,mid)+sum(id*2+1,mid+1,r); 76 } 77 void updata(int id,int pos,int val) 78 { 79     int mid=(node[id].left+node[id].right)/2; 80     if (node[id].left==pos&&node[id].right==pos) 81     { 82         node[id].sum+=val; 83         return ; 84     } 85     if (pos<=mid) 86         updata(id*2,pos,val); 87     else 88         updata(id*2+1,pos,val); 89     node[id].sum=node[id*2].sum+node[id*2+1].sum; 90 } 91 int a[5010]; 92 int main() 93 { 94     int n; 95     while(scanf("%d",&n)!=EOF) 96     { 97         int i,j; 98         int cnt=0; 99         build__tree(1,0,n-1);100         for(i=0; i<n; i++)101             scanf("%d",&a[i]);102         for(i=0; i<n; i++)103         {104             cnt+=sum(1,a[i],n-1);105             updata(1,a[i],1);106         }107         int min=cnt;108         for(i=0;i<n;i++)109         {110             cnt-=a[i];111             cnt+=n-a[i]-1;112             if (cnt<min)113                 min=cnt;114         }115         printf("%d\n",min);116     }117     return 0;118 }
View Code

 

HDU1394(Minimum Inversion Number)