hdu(1394)Minimum Inversion Number

来源:互联网 发布:mfc多文档编程实例 编辑:程序博客网 时间:2024/06/06 23:50

感觉此题还是用暴力比较方面,不过用线段树更快。。

 

题意:就是给出一串数,当依次在将第一个数变为最后一个数的过程中,要你求它的最小逆序数。

思路:可以用树状数组和线段数做。这里我是用线段树做的。建的是一棵空树,然后每插入一个点之前,统计大于这个数的有多少个,直到所有的数都插入完成,就结果了逆序树的统计。

//先用线段树求出初始的时候,逆序数的个数,再利用公式求最小的。。
//这个下标必须从零开始,不然会无法运行。

 

 

左移序列之后得到新的序列的逆序数的个数就等与当前总的
个数减左边的数的逆序数a[i],然后加上新增的逆序数n-a[i]-1
即sum=sum-a[i]+n-a[i]-1;


#include"stdio.h"
#include"string.h"
int sum;
int s[20000];
struct  point
{
 int x, y;
 int sum;
}a[60000];
void tree(int t,int x,int y)
{
 a[t].x=x;
 a[t].y=y;
 a[t].sum=0;
 if(x==y)
  return ;
 int temp=2*t;
 int mid=(x+y)/2;
 tree(temp,x,mid);
 tree(temp+1,mid+1,y);
}
void IN(int t,int x)
{
 if(a[t].x==a[t].y)
 {
  a[t].sum=1;
  return;
 }
 int temp=2*t;
 int mid=(a[t].x+a[t].y)/2;
 if(x<=mid)
  IN(temp,x);
 else
  IN(temp+1,x);
 a[t].sum=a[temp].sum+a[temp+1].sum;
}
void find(int t,int x,int y)
{
 if(a[t].x==x&&y==a[t].y)
 {
  sum+=a[t].sum;
  return ;
 }
 int temp=2*t;
 int mid=(a[t].x+a[t].y)/2;
 if(y<=mid)
  find(temp,x,y);
 else if(x>mid)
  find(temp+1,x,y);
 else
 {
  find(temp,x,mid);
  find(temp+1,mid+1,y);
 }
}
int main()
{
 int m,min,i;
 while(scanf("%d",&m)!=EOF)
 {
  tree(1,0,m-1);
  sum=0;
  for(i=0;i<m;i++)
  {
   scanf("%d",&s[i]);
   find(1,s[i],m-1);
   IN(1,s[i]);
  }
  min=sum;
  for(i=0;i<m;i++)
  {
   sum=sum-s[i]+m-s[i]-1;
   if(min>sum)
    min=sum;
  }
  printf("%d\n",min);
 }
 return 0;
}


 


#include"stdio.h"
#include"string.h"
int a[20000];
int main()
{
    int m,i,j,k,h;
    while(scanf("%d",&m)!=EOF)
    {
        for(i=1;i<=m;i++)
            scanf("%d",&a[i]);
        h=0;
        for(i=1;i<=m;i++)
            for(j=i+1;j<=m;j++)
            {
                if(a[i]>a[j])
                    h++;
            }
            k=h;
            for(i=1;i<=m;i++)
            {
                h=h-a[i]+(m-1)-a[i];
                if(k>h)
                    k=h;
            }
            printf("%d\n",k);
    }
    return 0;
}

 

原创粉丝点击