逆序对
题目描述
猫猫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; }