您的位置:首页 > 产品设计 > UI/UE

Ultra-QuickSort(树状数组求逆序对数)

2016-02-25 15:25 423 查看
Ultra-QuickSort
题目链接:http://poj.org/problem?id=2299

TimeLimit:7000MSMemoryLimit:65536K
TotalSubmissions:51641Accepted:18948
Description


Inthisproblem,youhavetoanalyzeaparticularsortingalgorithm.Thealgorithmprocessesasequenceofndistinctintegersbyswappingtwoadjacentsequenceelementsuntilthesequenceissortedinascendingorder.Fortheinputsequence
91054,
Ultra-QuickSortproducestheoutput
01459.
YourtaskistodeterminehowmanyswapoperationsUltra-QuickSortneedstoperforminordertosortagiveninputsequence.
Input

Theinputcontainsseveraltestcases.Everytestcasebeginswithalinethatcontainsasingleintegern<500,000--thelengthoftheinputsequence.Eachofthethefollowingnlinescontainsasingleinteger0≤a[i]≤999,999,999,thei-thinputsequenceelement.Inputisterminatedbyasequenceoflengthn=0.Thissequencemustnotbeprocessed.
Output

Foreveryinputsequence,yourprogramprintsasinglelinecontaininganintegernumberop,theminimumnumberofswapoperationsnecessarytosortthegiveninputsequence.
SampleInput

5
9
1
0
5
4
3
1
2
3
0

SampleOutput

6
0
题解:树状数组求逆序对数,就是求对于每一个数后面有多少个数字比它自己的数字小,那么从后向前遍历所有的数字,a[x]表示的是当前状态下小于等于x的值得个数.那么从后往前的扫描所有的数值统计后,再把这个数字对应的a[x]++;这样在扫描它前面的数的时候就相当于考虑这个数了,这种总是求a的前缀和和对单独点修改的操作可以使用树状数组解决。
注意这个题要解决的数很大,所以要离散化一下,这里介绍两种离散化的方法:
1.写一个二分查找的函数,先sort()一下,然后对于每个值,find(x)返回的下标值就是离散化后的结果,这里注意因为树状数组不能处理下标是0的情况,所以要将编号从1开始。而且要注意结果有可能会超int所以要用longlong,因为这个wa了好多次。
代码:


#include<cstdio>
#include<cstring>
#include<algorithm>
usingnamespacestd;
#definelllonglong
constllN=500005;
lla
;
llmp
;
lltree
;
lllowbit(llx){
returnx&(-x);
}
llsum(llx){
llans=0;
while(x>0){
ans+=tree[x];
x-=lowbit(x);
}
returnans;
}
voidadd(llx){
while(x<=N){
tree[x]++;
x+=lowbit(x);
}
}
lln;
llfind(llx){
lll=0;
llr=n-1;
llmid=(l+r)/2;
while(l<=r){
if(a[mid]==x)returnmid;
elseif(a[mid]<x)l=mid+1;
elseif(a[mid]>x)r=mid-1;
mid=(l+r)/2;
}
}
intmain()
{
while(~scanf("%d",&n))
{
if(n==0)return0;
memset(tree,0,sizeof(tree));
for(lli=0;i<n;i++){
scanf("%I64d",&mp[i]);
a[i]=mp[i];
}
sort(a,a+n);
llans=0;
for(lli=n-1;i>=0;i--){//从后往前扫描
mp[i]=find(mp[i])+1;
//prllf("%d\n",mp[i]);
ans+=sum(mp[i]-1);
//prllf("ans=%d",ans);
add(mp[i]);
}
printf("%I64d\n",ans);
}
return0;
}



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