4163 hzwer与逆序对
时间限制: 10 s
空间限制: 256000 KB
题目等级 : 黄金 Gold
题目描述 Description
hzwer在研究逆序对。
对于数列{a},如果有序数对(I,j)满足:i<j,a[i]>a[j],则(i,j)是一对逆序对。
给定一个数列{a},求逆序对个数。
输入数据较大,请使用scanf代替cin读入。
输入描述 Input Description
第一行一个数n,表示{a}有n个元素。
接下来n个数,描述{a}。
输出描述 Output Description
一个数,表示逆序对个数。
样例输入 Sample Input
5
3 1 5 2 4
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
对于10%数据,1<=n<=100.
对于20%数据,1<=n<=10000.
对于30%数据,1<=n<=100000.
对于100%数据,1<=n<=1000000,1<=a[i]<=10^8.


#include<cstdio> #include<iostream> using namespace std; #include<algorithm> #include<cstring> #define MAXN 1000001 struct node { long long v; int id; bool operator<(const node &p) const{return v<p.v;} }; node a[MAXN+10]; long long int c[MAXN+10],b[MAXN+10]; int n; inline int lowbit(int x) { return x&(-x); } long long query(int x) { long long ans=0; while(x) { ans+=c[x]; x-=lowbit(x); } return ans; } void change(int x) { while(x<=n) { c[x]++; x+=lowbit(x); } } int main() { scanf("%d",&n); memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); memset(b,0,sizeof(b)); for(int i=1;i<=n;++i) { scanf("%d",&(a[i].v)); a[i].id=i; } sort(a+1,a+n+1); int pre=-1; int prevalue=0; for(int i=1;i<=n;++i) { if(pre!=a[i].v) { pre=a[i].v; a[i].v=++prevalue; } else a[i].v=prevalue; } for(int i=1;i<=n;++i) b[a[i].id]=a[i].v; long long int s=0; for(int i=n;i>=1;--i) { change(b[i]); s+=query(b[i]-1); } cout<<s<<endl; return 0; }