POJ2299题解(树状数组)

POJ2299题解

2019-12-28

Powered by Gauss

1.题目传送门:POJ2299

 

2.理解题意:

做题的时候,第一步也是最重要的就是理解题意。记住这句话。

POJ2299是一道标准的树状数组模板题。题意大致如下:

快速排序是一种非常优秀的排序方式,其精华在于循环比较和swap函数的应用。

先给你一个数N,表示这组数据(没错,这题是多组数据)数的个数,之后的N行,每行一个数Ai

请你输出在快速排序过程中经历的swap函数的次数。

3.算法思路:

树状数组是一种非常高效的数据结构,由于篇幅有限,这里不做讲解,作者将尽快写出一篇树状数组的稿子,敬请谅解。

树状数组的精华在于lowbit函数的使用,为了迎合题目,这里将query函数和update函数做了一些改动。

void update(int x,int k)
{
    int i;
    for(i=x;i<=n;i=i+lowbit(i))
    {
        tree[i]+=k;
    }
}
int query(int x)
{
    int i,sum=0;
    for(i=x;i>0;i=i-lowbit(i))
    {
        sum+=tree[i];
    }
    return sum;
}

我们因为这道题的数据规模非常大,所以要用到一些离散化的思想。

for(i=1;i<=n;i++)
{
     cin>>a[i].value;
     a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++)
{
    a[i].pos=i;
}

有了离散化,我们就可以大大降低时间复杂度了。

上面那段代码中,我们用结构体node来实现,包含三个参数,id,pos和value。

struct node
{
  int id,value,pos;
}a[500001];

最后,结合树状数组的计算模板,我们给出最后的AC源代码,用时3610MS:

#include
#include
#include
#include
using namespace std;
int tree[500001],n;
struct node
{
  int id,value,pos;
}a[500001];
int lowbit(int x)
{
    return (x&(-x));
}
void update(int x,int k)
{
    int i;
    for(i=x;i<=n;i=i+lowbit(i))
    {
        tree[i]+=k;
    }
}
int query(int x)
{
    int i,sum=0;
    for(i=x;i>0;i=i-lowbit(i))
    {
        sum+=tree[i];
    }
  return sum;
}
int cmp(node a,node b)
{
    return a.value<b.value;
}
int cmp1(node a,node b)
{
    return a.id<b.id;
}
int main()
{
    int i;
    long long sum;
    while(cin>>n && n)
    {
        sum=0;
        memset(tree,0,sizeof(tree));
        for(i=1;i<=n;i++)
        {
            cin>>a[i].value;
            a[i].id=i;
        }
        sort(a+1,a+n+1,cmp);
        for(i=1;i<=n;i++)
        {
            a[i].pos=i;
        }
        sort(a+1,a+n+1,cmp1);
        for(i=1;i<=n;i++)
        {
            sum+=i-1-query(a[i].pos);
            update(a[i].pos,1);
        }
        cout<endl;
    }
    return 0;
}

版权声明:知识产权神圣不可侵犯,这篇文章中的部分代码和思想源自:https://blog.csdn.net/weixin_43918531/article/details/87950037

你可能感兴趣的:(POJ2299题解(树状数组))