HDU-1394-Minimum Inversion Number树状数组

来源:互联网 发布:成都网络综合布线 编辑:程序博客网 时间:2024/06/08 04:49

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

给一个整数n,接下来有n个数。每次将第一个值放到该数列的最后,循环n次。
对于每一次变换求它的逆序数,找出最小值。

首先要用树状数组来求逆序数。
其次,
假设每次移动的值为a[i]
对于每一次状态变换而言:当前的逆序数=上个状态的逆序数+a-(b-1)
a是指当前序列中比a[i]大的数;
(b-1)是指当前序列中比a[i]小的数。
因为每一次把a[i]移动到最后的时候,比他大的数原本不构成逆序对,但是移动到最后构成了逆序对,所以要加比它大的数。同理,原本比它小的数构成逆序对,但是移动到最后不够成逆序对,所以要减去。
OVER!
贴代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long int LL;const int MAXL(500000);struct node{    int x;    int order;} s[MAXL+50];int c[MAXL+50];int dis[MAXL+50];//这里离散化了一下数组,但是本题数据量小,没有必要。int n;bool cmp(struct node p,struct node q){    return p.x<q.x;}int lowbit(int k){    return k&(-k);}void Update(int i,int value){    while(i<=n)    {        c[i]+=value;        i+=lowbit(i);    }}int Getsum(int i){    int ans=0;    while(i>0)    {        ans+=c[i];        i-=lowbit(i);    }    return ans;}int min(int x,int y){    return x>y?y:x;}int main(){    while(~scanf("%d",&n))    {        memset(c,0,sizeof(c));        for(int i=1; i<=n; i++)        {            scanf("%d",&s[i].x);            s[i].order=i;        }        sort(s+1,s+n+1,cmp);        for(int i=1; i<=n; i++)            dis[s[i].order]=i;        LL ans=0;        for(int i=1; i<=n; i++)        {            Update(dis[i],1);            ans+=i-Getsum(dis[i]);        }        int MIN=ans;        for(int i=1;i<=n;i++)        {            ans=ans+(n-dis[i])-(dis[i]-1);            MIN=min(MIN,ans);        }        cout<<MIN<<endl;    }}
原创粉丝点击