zoukankan      html  css  js  c++  java
  • HDU 1394 Minimum Inversion Number(线段树 或 树状数组)

    题目大意:给出从 0 到 n-1 的整数序列,A0,A1,A2...An-1。可将该序列的前m( 0 <= m < n )个数移到后面去,组成其他的序列,例如当 m=2 时,得到序列 A2,A3...An-1,A0,A1 。我们定义逆序对<Ai,Aj>满足 i < j 且Ai > Aj 。 在所有的序列中找出逆序对最少的序列,输出逆序对个数。num[n+1]存储序列元素。
    思路: 假设某个序列的逆序对个数为 sum 则下一个序列的逆序对个数为 sum - num[1] + (n - 1) - num[1]。则只需要求出原始序列的逆序对个数计科推出后面的所有序列的逆序对个数。
    再输入每个元素的时候统计区间 [num[i]+1,n-1] 之间的元素已经能出现的总次数,则可以用线段树,或树状数组统计。下面给出两种方法的代码。

    树状数组:

      #include<iostream>
      #include<cstdio>
      #include<cstdlib>
      #include<cstring>
      #include<queue>
      #include<algorithm>
      #include<cmath>
      #include<map>
      using namespace std;
      #define INF 0x7fffffff
    
      int a[5010],c[5010],n;
    
      int lowbit(int x){
       return x & (-x) ;
      }
    
      void add(int x,int d){
       while(x <= n){
    	c[x] += d;
    	x = x + lowbit(x) ;
       }
      }
    
      int getsum(int x){
       int ans = 0;
       while(x > 0){
    	ans += c[x] ;
    	x = x - lowbit(x) ;
       }
       return ans ;
      }
    
      int main(){
       int i,j,x,num[5010];
       while(~scanf("%d",&n) && n){
    	int sum = 0;
    	memset(c,0,sizeof(c));
    	for(i=1;i<=n;i++){
    		scanf("%d",&x) ;
    		num[i] = x ;
    		x ++ ;
    			sum += getsum(n) - getsum(x) ;
    		add(x,1);
    	}
    	int ans = sum ;
    	for(i=1;i<n;i++){
    		sum = sum - (num[i] + 1) + n - num[i] ;
    		ans = min(ans,sum);
    	}
    	cout << ans << endl;
       }
       return 0;
      }
    

    线段树

      #include<iostream>
      #include<cstdio>
      #include<cstdlib>
      #include<cstring>
      #include<queue>
      #include<algorithm>
      #include<cmath>
      #include<map>
      using namespace std;
      #define INF 0x7fffffff
    
      int n,x;
      struct node{
       int l,r,sum;
      }a[20100];
    
      void buildtree(int i,int l,int r){
       a[i].l = l ;
       a[i].r = r;
       a[i].sum = 0;
       if(l == r)
    	return ;
       int mid = (l+r)/2;
       buildtree((i<<1),l,mid);
       buildtree(i*2+1,mid+1,r);
      }
    
      int query(int i,int l,int r){
       if(l>r)
           return 0;
       if(a[i].l == l && a[i].r == r)
           return a[i].sum;
       int sum = 0;
       int mid = (a[i].l + a[i].r) / 2 ;
       if(r<=mid)
           sum = query(i*2,l,r);
       else if(l > mid)
           sum = query(i*2+1,l,r);
       else
           sum = query(i*2,l,mid) + query(i*2+1,mid+1,r) ;
       return sum ;
      }
    
      void update(int i,int x){
       if(a[i].l == x && a[i].r == x){
           a[i].sum ++;
       }
       else{
    	a[i].sum ++;
    	int mid = (a[i].l + a[i].r) / 2 ;
    	if(x<=mid)
    	    update(i*2,x);
    	else
    	    update(i*2+1,x);
       }
      }
    
      int main(){
       int i,j,sum,num[5010];
       while(~scanf("%d",&n) && n ){
    	sum = 0 ;
    	buildtree(1,0,n-1);
    	for(i=1;i<=n;i++){
    		scanf("%d",&x);
    		num[i] = x ;
    		sum += query(1,x+1,n-1);
    		update(1,x);
    	}
    	int ans = sum;
    	for(i=1;i<n;i++)
    	{
    		sum = sum - num[i] + n-num[i]-1 ;
    		ans = min(ans,sum);
    	}
    	cout << ans << endl ;
    } 
    
    return 0;
  • 相关阅读:
    转:页面Postback后定位滚动条不再难
    c:\windows\microsoft.net\framework\v1.1.4322\Config\machine.config 行: 198
    WebService相关概念和原理(中间层)
    JS 根据DropDownList的Text选中某一项
    javascript事件列表解说
    AJAXUpdateProgress设置CSS元素POSITION的使动画居中 & loading的Info
    ASP.NET2.0 Skin+CSS 测试
    C# 日期格式转换(转)
    编写代码创建DataTable对象
    ToString 格式化数值
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4761507.html
Copyright © 2011-2022 走看看