猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。
最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 a_i>a_j 且 i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入格式
第一行,一个数 n,表示序列中有 n个数。
第二行 n 个数,表示给定的序列。序列中每个数字不超过 10^9。
输出格式
输出序列中逆序对的数目。
n<=5e5
线段树或者树状数组都可以,离散化的时候可以先排序然后用lower_bound找
#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=5e5;
int value[maxn+100];
struct SegTreeNode
{
int val;
};
SegTreeNode tree[maxn*4+100];
int a[maxn+100];
void updateOne(int root,int nstart,int nend,int index,int addVal);
int query(int root,int nstart,int nend,int qstart,int qend);
int main()
{
int n,cnt;
ll ans;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=4*n;i++) tree[i].val=0;
cnt=0;
ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&value[i]);
a[i]=value[i];
}
sort(value+1,value+1+n);
cnt=unique(value+1,value+1+n)-value-1;
for(int i=1;i<=n;i++)
{
int temp=lower_bound(value+1,value+1+cnt,a[i])-value;
updateOne(1,1,cnt,temp,1);
ans+=query(1,1,cnt,temp+1,cnt);
}
cout<<ans<<endl;
}
return 0;
}
void updateOne(int root,int nstart,int nend,int index,int addVal)
{
if(nstart==nend)
{
tree[root].val+=1;
return;
}
int mid=(nstart+nend)/2;
if(index<=mid)
updateOne(root*2,nstart,mid,index,addVal);
else updateOne(root*2+1,mid+1,nend,index,addVal);
tree[root].val=tree[root*2].val+tree[root*2+1].val;
}
int query(int root,int nstart,int nend,int qstart,int qend)
{
if(qstart>nend||qend<nstart) return 0;
if(qstart<=nstart&&qend>=nend)
return tree[root].val;
int mid=(nstart+nend)/2;
return query(root*2,nstart,mid,qstart,qend)+query(root*2+1,mid+1,nend,qstart,qend);
}