• 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;
  • 相关阅读:
    .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求
    .netcore持续集成测试篇之搭建内存服务器进行集成测试一
    .netcore持续集成测试篇之Xunit数据驱动测试
    .netcore持续集成测试篇之开篇简介及Xunit基本使用
    .net持续集成测试篇之Nunit 测试配置
    .net持续集成测试篇之Nunit参数化测试
    .net持续集成测试篇之Nunit that断言
    .net持续集成测试篇之Nunit文件断言、字符串断言及集合断言
    .net持续集成测试篇之Nunit常见断言
    .net持续集成单元测试篇之单元测试简介以及在visual studio中配置Nunit使用环境
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4761507.html
Copyright © 2020-2023  润新知