hdu 1394Minimum Inversion Number

本题为是对逆序对的查找,问题可为在某个区间共有多少个数被输入,首先为查找初始的逆序对数,然后求将第一个数加入到最后的逆序对数,设初始的逆序对数总共为SUM这将第一个数加入到最后的的逆序对数为SUM加上比A1大的数减去比A1小的数字。即为当前的逆序对数,如此类推,求的比逆序对数最小的。。。

 

 

 

View Code
#include<cstdio>

#include<cstdlib>

#include<cstdlib>

#include<cstring>

#define MAXN  5010

int seg_tree[MAXN<<2];

void build_tree(int l,int r,int id);

int query_tree(int left,int right,int l,int r,int id);

void update_tree(int left,int right,int l,int r,int id);

void push_up_tree(int id);

int x[MAXN];

int main()

{

    int n,i,j,k,sum;

    while(scanf("%d",&n)==1)

    {

        sum=0;

        build_tree(0,n-1,1);

        for(i=0;i<n;i++)

        {

            scanf("%d",x+i);

            

        }

        for(i=n-1;i>=0;i--)

        {

            sum+=query_tree(0,x[i],0,n-1,1);

            update_tree(x[i],x[i],0,n-1,1);

        }

        int ret=sum;

        for(i=0;i<n;i++)

        {

            sum+=n-1-x[i]-x[i];

            if(ret>sum)

                ret=sum;

        }

        printf("%d\n",ret);



    }

}

void build_tree(int l,int r,int id)

{

    if(l==r)

    {seg_tree[id]=0;

    return ;

    }

    int m=(l+r)>>1;

    build_tree(l,m,id<<1);

    build_tree(m+1,r,id<<1|1);

    push_up_tree(id);

}

int query_tree(int left,int right,int l,int r,int id)

{

    if(left<=l&&right>=r)

        return seg_tree[id];

    int m=(l+r)>>1,ret=0;

    if(left<=m)

        ret+=query_tree(left,right,l,m,id<<1);

    if(right>m)

        ret+=query_tree(left,right,m+1,r,id<<1|1);

    return ret;

}

void update_tree(int left,int right,int l,int r,int id)

{

    if(l==r)

    {seg_tree[id]++;

    return ;

    }

    int m=(l+r)>>1;

    if(left<=m)

        update_tree(left,right,l,m,id<<1);

    else update_tree(left,right,m+1,r,id<<1|1);

    push_up_tree(id);



}

void push_up_tree(int id)

{

    seg_tree[id]=seg_tree[id<<1]+seg_tree[id<<1|1];

}

你可能感兴趣的:(version)