经过两天的调试终于弄明白了线段树求逆序数,;
说一下思路:
首先建树是根据序列中最大的数开辟的区间,(如果数太大 离散化)。
逆序对可以表示成一个数前面有几个比这个数大的数,就表示这个数所形成的逆序对数,(听绕口的,需要模拟一下);
数列a[i],将数列a[i]添加到线段树中,并将区间中有它的区间的num+1,意思是在当前的区间上有几个值了,记录下来。
因为是从a[1]->a[n]遍历的,所以每次加进a[i]时,都查询一下在区间1-a[i]上有几个值了,有几个值就表示在a[i]之前的前i个值中有几个比a[i]小的了。
(讲起来有点啰嗦,直接看代码吧)
#include <iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct node
{
int l,r;
int num;
} A[10000];
int a[1000];
void build(int node,int l,int r)
{
A[node].l=l;
A[node].r=r;
A[node].num=0;
if(l==r)
{
return;
}
build(2*node,l,(l+r)/2);
build(2*node+1,(l+r)/2+1,r);
}
void in(int node,int l,int r,int x)
{
//cout<<"++"<<node<<" "<<l<<" "<<r<<" "<<x<<endl;
if(l==A[node].l&&A[node].r==r)
{
A[node].num+=x;
// cout<<node<<" "<<A[node].num<<"***\n";
//return ;
}
else
{
int mid=(A[node].l+A[node].r)/2;
if(l<=mid)
in(2*node,l,r,x);
if(r>mid)
in(2*node+1,l,r,x);
A[node].num=A[node*2].num+A[node*2+1].num;
}
}
int query(int node,int l,int r)
{
if(l<=A[node].l&&A[node].r<=r)
{
return A[node].num;
}
else
{
int ans=0;
int mid=(A[node].l+A[node].r)/2;
if(l<=mid)
ans+=query(node*2,l,r);
if(r>mid)
ans+=query(node*2+1,l,r);
return ans;
}
}
int main()
{
int n;
memset(A,0,sizeof(A));
cin>>n;
int mx=0;
for(int i=1; i<=n; i++)
{
cin>>a[i];
if(a[i]>mx)mx=a[i];
}
build(1,1,mx);
/*cout<<A[1].num<<"--"<<A[1].l<<" "<<A[1].r<<endl;
cout<<A[2].num<<"--"<<A[2].l<<" "<<A[2].r<<"\t";
cout<<A[3].num<<"--"<<A[3].l<<" "<<A[3].r<<endl;
cout<<A[4].num<<"--"<<A[4].l<<" "<<A[4].r<<"\t";
cout<<A[5].num<<"--"<<A[5].l<<" "<<A[5].r<<"\t";
cout<<A[6].num<<"--"<<A[6].l<<" "<<A[6].r<<"\t";
cout<<A[7].num<<"--"<<A[7].l<<" "<<A[7].r<<endl;
cout<<A[8].num<<"--"<<A[8].l<<" "<<A[8].r<<"\t";
cout<<A[9].num<<"--"<<A[9].l<<" "<<A[9].r<<endl;*/
int sum=0;
for(int i=1; i<=n; i++)
{
int k=a[i];
in(1,k,k,1);
/*cout<<"------------------------------------\n";
cout<<A[1].num<<"--"<<A[1].l<<" "<<A[1].r<<endl;
cout<<A[2].num<<"--"<<A[2].l<<" "<<A[2].r<<"\t";
cout<<A[3].num<<"--"<<A[3].l<<" "<<A[3].r<<endl;
cout<<A[4].num<<"--"<<A[4].l<<" "<<A[4].r<<"\t";
cout<<A[5].num<<"--"<<A[5].l<<" "<<A[5].r<<"\t";
cout<<A[6].num<<"--"<<A[6].l<<" "<<A[6].r<<"\t";
cout<<A[7].num<<"--"<<A[7].l<<" "<<A[7].r<<endl;
cout<<A[8].num<<"--"<<A[8].l<<" "<<A[8].r<<"\t";
cout<<A[9].num<<"--"<<A[9].l<<" "<<A[9].r<<endl;
cout<<"k="<<k<<endl;
cout<<"kdsjfha=="<<query(1,1,k)<<endl;*/
sum+=(i-query(1,1,k));
}
cout<<sum<<endl;
return 0;
}