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;
}
这里关键就是如何用通过一系列求和操作求出逆序对数
假设我们对于任何一个序列 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;
}
相关文章推荐
- poj2299 (树状数组+离散化)
- poj 2299 求逆序数 树状数组入门
- poj2299(离散化+树状数组)
- 树状数组入门基础题 南阳oj 116
- 树状数组入门hdu1166,hdu1541,poj1195,poj2299
- PKU 2299 求解逆序数(使用归并或者树状数组) 树状数组及入门知识
- HDU 1166 敌兵布阵【树状数组入门题】
- poj2299 离散化+树状数组
- poj 2352 入门树状数组
- poj2299 树状数组入门题
- 入门树状数组(左边比x小的个数)
- 树状数组入门 (记录一下
- poj2299 Ultra-QuickSort 二叉排序树或树状数组
- poj2299 Ultra-QuickSort(归并排序 || 离散化+树状数组)
- POJ2299 Ultra-QuickSort 树状数组
- HDU 1166 敌兵布阵【线段树,树状数组入门题,单点更新,区间求和】
- hdu 1541 Stars 入门 树状数组
- poj2299 (离散化+树状数组)或(归并排序)
- 【HDU 1541】 树状数组(入门题)
- Ant入门-配置和使用