zoukankan      html  css  js  c++  java
  • hdu1394逆序数(线段树)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1394

    题目大意:逆序数:即假设在数组a中,假如i<j,但是a[i]>a[j]。

    现在有一个数组,含有n个数(为0-(n-1)的一个排列),依次把第一个数,放到数组最后面,求其中逆序数数目最小是多少?

    例:

    Sample Input
    10 1 3 6 9 0 8 5 7 4 2
     
    Sample Output
    16

    解题思路:首先,我们要思考对于一个数组怎样求出它的逆序数的总个数,这里有两种方法,最简单的是,直接暴力,两层循环就可以搞定。这里主要讲一下第二种方法,用线段树也可以很巧妙的求它的逆序数个数,我们先建立一颗空树,然后一个一个将节点插入树中,我们把数组中数的大小看成在树中的位置,然后每插入一个节点,就统计大于这个数的数目,即产生的逆序数的数目,然后再更新该位置的数值为1.这样就求出了初始状态下的逆序数sum了。

    然后要求出最小的逆序数,因为数组是0到n-1的一个排列,所以如果当你把第一个数从第一个放到最后一个的时候,逆序数就会减少a【i】个,同时增加n-(a[i]+1)个。所以我们只需要枚举依次把第一个数放到最后位置,所产生的逆序数sum+(n-2*num[i]-1)取最小值即可。

    附上代码

    暴力解法

    #include<iostream>
    using namespace std;
    #define inf 0x3f3f3f3f
    int n,a[5005];
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=i+1;j<=n;j++)
                {
                    if(a[i]>a[j])
                        sum++;
                }
            }
            int ans=inf;
            for(int i=1;i<=n;i++)
            {
                sum+=(n-2*a[i]-1);
                ans=min(ans,sum);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    线段树解法

    #include<iostream>
    #include<cstring>
    using namespace std;
    #define ll long long
    #define maxn 10005
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define pushup() tree[root]=tree[root<<1]+tree[root<<1|1]
    int n,tree[maxn<<2],num[maxn<<2];
    
    /*
    void pushdown(int l,int r,int root)
    {
        if(add[root])
        {
            add[root<<1]+=add[root];
            add[root<<1|1]+=add[root];
            tree[root<<1]+=l*add[root];
            tree[root<<1|1]+=r*add[root];
            add[root]=0;
        }
    }
    void build(int l,int r,int root)
    {
        add[root]=0;
        if(l==r)
        {
            tree[root]=num[tot++];
            return;
        }
        int mid=l+r>>1;
        build(lson);
        build(rson);
        pushup();
    }*/
    void update(int pos,int val,int l,int r,int root)
    {
        if(l==r)
        {
            tree[root]=val;
            return;
        }
        int mid=l+r>>1;
        if(pos<=mid)
            update(pos,val,lson);
        else
            update(pos,val,rson);
        pushup();
    }
    int query(int L,int R,int l,int r,int root)
    {
        if(L<=l&&R>=r)
            return tree[root];
        int ans=0,mid=l+r>>1;
        if(L<=mid)
            ans+=query(L,R,lson);
        if(R>mid)
            ans+=query(L,R,rson);
        return ans;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            memset(tree,0,sizeof(tree));//初始时,为空树,直接memset
            int sum=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&num[i]);
                sum+=query(num[i]+1,n,1,n,1);
                update(num[i]+1,1,1,n,1);
            }
            int ans=sum;
            for(int i=1;i<=n;i++)
            {
                sum+=(n-2*num[i]-1);
                ans=min(ans,sum);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Java EE (3) -- Java EE 6 Web Services Developer Certified Expert(1z0-897)
    二、用电信号传输 TCP/IP 数据(1)
    P2384 最短路 洛谷
    T1231 最优布线 codevs
    P3371 单源最短路径【模板】 洛谷
    spfa【模板】
    P1396 营救 洛谷
    解决Android加固多进程ptrace反调试的思路整理
    Android Dex文件格式解析
    360加固保so动态脱壳
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/9693188.html
Copyright © 2011-2022 走看看