杭电 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级别。

你可能感兴趣的:(version)