对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。
求这段正整数序列中逆序对的数目。
Input
第一行,一个数n,表示序列中有n个数。N<=5*10^5
第二行n个数,表示给定的序列。序列中每个数字不超过10^9
Output
给定序列中逆序对的数目。
Sample Input
6
5 4 2 6 3 1
Sample Output
11
#include<bits/stdc++.h>
using namespace std;
long long a[500005],ans,n;
struct MM
{
long long ii,num;
}b[500005];
struct MMM
{
long long l,r,sum;
}tree[2000005];
bool cmp(MM x,MM y)
{
return x.num<y.num;
}
void build(long long root,long long L,long long R)
{
tree[root].l=L;
tree[root].r=R;
if(tree[root].l==tree[root].r)
return;
long long mid=(L+R)>>1;
build(root<<1,L,mid);
build(root<<1|1,mid+1,R);
return;
}
void updata(long long root,long long v)
{
if(tree[root].l==tree[root].r)
{
tree[root].sum++;
return;
}
long long mid=(tree[root].l+tree[root].r)>>1;
if(v<=mid)
updata(root<<1,v);
else
updata(root<<1|1,v);
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
return;
}
long long query(long long root,long long x)
{
if(tree[root].l==tree[root].r)
return tree[root].sum;
long long mid=(tree[root].l+tree[root].r)>>1;
if(x<=mid)
return query(root<<1,x)+tree[root<<1|1].sum;
return query(root<<1|1,x);
}
int main()
{
cin>>n;
for(long long i=1;i<=n;i++)//这里离散化开始
{
cin>>a[i];
b[i].num=a[i];
b[i].ii=i;
}
sort(b+1,b+n+1,cmp);
for(long long i=1,j=0;i<=n;i++)
{
if(b[i].num!=b[i-1].num||i==1) j++;
a[b[i].ii]=j; //a[i]=j,输入的第i个数字排序后第j小
}
build(1,1,n);
for(long long i=1;i<=n;i++)
{
ans+=query(1,a[i]+1);
//query查询在线段树中>=a[i]+1数字,出现了多少次
updata(1,a[i]);//在权值线段树中,将a[i]这个数字出现的次数加1
}
cout<<ans<<endl;
return 0;
}
原文:https://www.cnblogs.com/cutemush/p/11788999.html