P1908 逆序对
标签
相关讨论
进入讨论版推荐题目
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入格式
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。序列中每个数字不超过10910^9109
输出格式
给定序列中逆序对的数目。
输入输出样例
输入 #1
6 5 4 2 6 3 1
输出 #1
11
说明/提示
对于25%的数据,n≤2500n leq 2500n≤2500
对于50%的数据,n≤4×104n leq 4 imes 10^4n≤4×104。
对于所有数据,n≤5×105n leq 5 imes 10^5n≤5×105
请使用较快的输入输出
应该不会n方过50万吧 by chen_zhe
解题思路: 注意下相等的情况
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <vector> 5 #include <algorithm> 6 #define ll long long 7 using namespace std; 8 int n; 9 const int N=5e5+5; 10 int arr[N],cnt[N]; 11 vector<int> vec; 12 int getid(int x) { return lower_bound(vec.begin(),vec.end(),x)-vec.begin()+1; } 13 int lowbits(int x) { return x&-x; } 14 void add(int x){ 15 while(x<=N) cnt[x]++,x+=lowbits(x); 16 } 17 int query(int x){ 18 int sum=0; 19 while(x>0) sum+=cnt[x],x-=lowbits(x); 20 return sum; 21 } 22 23 int main(){ 24 scanf("%d",&n); 25 for(int i=1;i<=n;i++) scanf("%d",&arr[i]),vec.push_back(arr[i]); 26 sort(vec.begin(),vec.end());vec.erase(unique(vec.begin(),vec.end()),vec.end()); 27 ll sum=0; 28 for(int i=n;i>=1;i--){ 29 add(getid(arr[i])); 30 sum+=query(getid(arr[i])-1); 31 } 32 printf("%lld ",sum); 33 return 0; 34 }