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];
}
原文地址:https://www.cnblogs.com/woaiyy/p/2522871.html