杭电 HOJ 1394 Minimum Inversion Number 解题报告

    让我们求的是最少的ai>aj数。看到题目是没啥思路。。。在网上搜了一下,有暴力的,有线段树的。

    暴力的比较简洁,也很容易弄懂,代码如下:

#include <iostream>
using namespace std;
int s[5001];
int main()
{
    int i,j,n,m,a;
    while(cin>>n)
    {
        for(m=i=0;i<n;i++)
            for(cin>>s[i],j=0;j<i;j++)
                if(s[j]>s[i])
                    m++;
        a=m;
        for(i=0;i<n;i++)
            if(a>(m=m+n-s[i]*2-1))
                a=m;
        cout<<a<<endl;
    }
}

    然后线段树是我自己写的(看过大牛的思路后得到启示。。。)

    在输入s[i]后,我们要比较所有先输入的比它大的数字的数量。用线段树保存并更新,查询会快很多。代码如下:

#include <iostream>
using namespace std;
int s[16384],p[5001];
int main()
{
    int i,j,n,m,a,t,sta,sum,v;
    while(cin>>n)
    {
        m=0;
        memset(s,0,sizeof(s));

        t=n-1;
        sta=0;
        while(t)
        {
            t>>=1;
            sta++;
        }
        sta=1<<sta;

        for(i=0;i<n;i++)
        {
            cin>>t;
            p[i]=t;
            
            t+=sta;
            v=t;
            while(v)
            {
                s[v]+=1;
                v>>=1;
            }

            sum=0;
            v=sta*2-1;
            if(t<v)
            {
                t++;
                for(;v!=t;t>>=1,v>>=1)
                    if(t&1)
                        sum-=s[t-1];
                m+=sum+s[t];
            }
        }
        a=m;
        for(i=0;i<n;i++)
            if(a>(m=m+n-p[i]*2-1))
                a=m;
        cout<<a<<endl;
    }
}

    代码不怎么好看,见谅。刚接触线段树,用的不是很熟,不过还是很强大的。用了2分的思想,问题的复杂度就会降到logN级别。

posted @ 2013-02-28 01:16  SF-_-  阅读(202)  评论(0编辑  收藏  举报