您的位置:首页 > 其它

poj 2299(离散化+树状数组)

2015-11-04 00:21 447 查看
区域赛的打击好大。。。直接就是铁了。

就是自己不努力的结果

好浮躁

还是要沉下心来做好一件事

算法是核心的东西。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

这个题就是求逆序数的对数,就是前一个数比后一个数大

怎么用树状数组呢?就是比如 9 6 5 11 3,先将1插入9的位置,然后i-sun(a[9]),是0,i是插入的第几个数,a数组是树状数组的那个数组,然后1插入位置6,这时候是2-sum(a[6]),发现是1,所以就是有一对了,这个意思很明显,就是看前面有几个数插入到了这个数的前面,有几个就有几个正序的数对呗。

然后是离散化,刚才的例子能看出来,数组开到了11,如果一个数更大一点,极端一点,会很大很大,不如将这五个数分别用4 3 2 5 1代替,只是表示他们的大小关系而不关心他们的值,用sort排序就好,嘿嘿~

当然了树状数组要熟练!

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

using namespace std;

int aa[500001];

struct node

{

    int val,xu;

    int xinxu;

}a[500001];

bool cmp(node a,node b)

{

    return a.val<b.val;

}

bool cmp1(node a,node b)

{

    return a.xu<b.xu;

}

int n;

int lowbit(int x)

{

    return x&-x;

}

void add(int x,int val)

{

    while(x<=n)

    {

        aa[x]+=val;

        x+=lowbit(x);

    }

}

int sum(int x)

{

    int s = 0;

    while(x>0)

    {

        s+=aa[x];

        x-=lowbit(x);

    }

    return s;

}

int main()

{

    while(scanf("%d",&n)!=EOF)

    {

        memset(aa,0,sizeof(aa));

        if(n==0) break;

        int i,j;

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

        {

            scanf("%d",&a[i].val);

            a[i].xu = i;

            //a[i].xinxu = 0;

        }

        sort(a+1,a+n+1,cmp);

        //for(i = 1;i<=n;i++) printf("* %d\n ",a[i].xu);

        for(i = 1;i<=n;i++) a[i].xinxu=i;

        sort(a+1,a+n+1,cmp1);  //两次sort明显慢了。。。。可以不用的

        //for(i=1;i<=n;i++) printf("& %d\n",a[i].xinxu);

        //for(i=1;i<=n;i++) printf(" %d\n",a[i].val);

        long long summm = 0;

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

        {

            add(a[i].xinxu,1);

            summm+=i-sum(a[i].xinxu);

        }

        printf("%lld\n",summm);

    }

    return 0;

}

时间少一点的代码:

#include <iostream>

#include <cstdio>

#include <string.h>

#include <algorithm>

using namespace std;

int a[500001],b[500001];

int n;

struct node

{

    int val,xu;

}c[500001];

bool cmp(node a,node b)

{

    return a.val<b.val;

}

int lowbit(int x)

{

    return x&-x;

}

void add(int x,int val)

{

    while(x<=n)

    {

        a[x]+=val;

        x+=lowbit(x);

    }

}

int sum(int x)

{

    int s=0;

    while(x>0)

    {

        s+=a[x];

        x-=lowbit(x);

    }

    return s;

}

int main()

{

    int i;

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

    {

        memset(a,0,sizeof(a));

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

        {

            scanf("%d",&c[i].val);

            c[i].xu=i;

        }

        sort(c+1,c+n+1,cmp);

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

        {

            b[c[i].xu]=i;

        }

        long long int summ = 0;

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

        {

            add(b[i],1);

            summ+=i-sum(b[i]);

        }

        printf("%lld\n",summ);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: