您的位置:首页 > 其它

HDU 1394 Minimum Inversion Number 树状数组

2016-08-23 16:58 295 查看
Description

The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. 

For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following: 

a1, a2, ..., an-1, an (where m = 0 - the initial seqence) 

a2, a3, ..., an, a1 (where m = 1) 

a3, a4, ..., an, a1, a2 (where m = 2) 

... 

an, a1, a2, ..., an-1 (where m = n-1) 

You are asked to write a program to find the minimum inversion number out of the above sequences. 

Input

The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1. 

Output

For each case, output the minimum inversion number on a single line. 

Sample Input

10
1 3 6 9 0 8 5 7 4 2


Sample Output

16


这题就是找规律,因为第一种情况的值是依次插入,并寻找后面的比他小的且未被取到的点的个数和就行,求出第一种情况的值之后,之后的情况的值就是前一种情况加上比那移到后面的一点大的点的个数再减去比后面一点小的点的个数,这样依次类推找最小值就行。

#include <stdio.h>
#include <string.h>
const int n=5000;

int c[n+10];
int a[n+10];
int lowbit(int k)
{
return (k&(-k));
}

int sum(int x) //求和
{
int ret = 0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}

void add(int x,int d) //修改节点的值
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
}

int main()
{
int t;
while(~scanf("%d",&t))
{
memset(a,0,sizeof(a));
int i,j;
for(i=0;i<t;i++)
{
scanf("%d",&a[i]);
a[i]=a[i]+1;
}
int min=0x3f3f3f3f;
int pre=0;
memset(c,0,sizeof(c));
for(i=0;i<t;i++)
{
pre+=a[i]-1-sum(a[i]-1);
add(a[i],1);
}
min=pre;
for(i=0;i<t-1;i++)
{
pre+=t-a[i]-(a[i]-1);
if(pre<min)
min=pre;
}
printf("%d\n",min);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: