您的位置:首页 > 其它

poj2299 树状数组入门题

2012-03-22 09:15 176 查看
/*

这里关键就是如何用通过一系列求和操作求出逆序对数

假设我们对于任何一个序列 a1,a2,a3,a4,a5....an

那么 我们首先对于每一个数 依次进行一次 update(ai,1) (i=1....n)

这里实质上就是 在树状数组中把大于等于ai的 数以此更新加1

然后getsum(ai) 这其实求的就是在树状数组中1...ai ,

1.如果在前面的过程中没有比ai小的数,那么此时用i-getsun(ai) 求出的

就是到目前为止有多少前面有多少比他大的数 ,

2.如果在前面有比ai小的数,因为update(ai,1)已经包括进去,然后用i-getsum(ai)就是对的,



这里要用位的思维方式来理解 时间复杂度也是nlogn

更详细的见这里

http://blog.csdn.net/jiejiuzhang1579/article/details/6877725

*/

#include<iostream>

#include<algorithm>

#include<iterator>

#define maxn 500006

using namespace std;

int tree[maxn];

struct node

{

int val;

int no;

};

node num[maxn];

bool cmp(node a,node b)

{

return a.val<b.val;

}

int lowbit(int x)

{

return x&(-x);

}

void update(int node,int val)

{

while(node<maxn)

{

tree[node]+=val;

node+=lowbit(node);

}

}

int getsum(int node)

{

int sum=0;

while(node>0)

{

sum+=tree[node];

node-=lowbit(node);

}

return sum;

}

int main()

{

int n;

long long sum;

int aa[maxn];

while(cin>>n&&n!=0)

{

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

{

cin>>num[i].val;

num[i].no=i;

}

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

memset(tree,0,sizeof(tree));

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

{

aa[num[i].no]=i;

}

sum=0;

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

{

update(aa[i],1);

sum+=(i-getsum(aa[i]));

}

cout<<sum<<endl;

}

system("pause");

return 0;

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