题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入格式
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。序列中每个数字不超过10^9109
输出格式
给定序列中逆序对的数目。
输入输出样例
输入 #1复制
6
5 4 2 6 3 1
输出 #1复制
11
说明/提示
对于25%的数据,n \leq 2500n≤2500
对于50%的数据,n \leq 4 \times 10^4n≤4×104。
对于所有数据,n \leq 5 \times 10^5n≤5×105
请使用较快的输入输出
应该不会n方过50万吧 by chen_zhe
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int tree[500010],rank[500010],n;
long long ans;
struct point{
int num,val;
}a[500010];
inline bool cmp(point q,point w){
if(q.val==w.val){
return q.num<w.num;
}
return q.val<w.val;
}
inline void insert(int p,int d){
for(;p<=n;p+=p&-p){
tree[p]+=d;
}
}
inline int query(int p){
int sum=0;
for(;p;p-=p&-p){
sum+=tree[p];
}
return sum;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].val);
a[i].num=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
rank[a[i].num]=i;
}
for(int i=1;i<=n;i++){
insert(rank[i],1);
ans+=i-query(rank[i]);
}
printf("%lld",ans);
return 0;
}
介绍了一种高效计算逆序对数量的方法,适用于竞赛编程中针对大规模数据集的问题解决。通过离线排序和分段树更新策略,实现了快速统计。
728

被折叠的 条评论
为什么被折叠?



