以前一直不知道线段树有求逆序对的功能
之前老师提了一下又刚好没听
今天自己模拟了一遍似乎是对了
代码虽短但耗费的空间却大
而归并排序代码虽然复杂却只耗费少量的空间
大概思想:
1.建一棵和最大数值一样大的线段树
2.每次在树中查找这个点的位置
3.在查找的过程中有两种选择
(1).往左子树下去
这时需要将当前节点的值减去左节点的值
(2).往右子树下去
不用操作
4.进入子树,直到遇到这个值所在的区间(l=r=a)的时候
5.将这个区间的值加1,然后维护树
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 int n,a[100010],c[400010],maxn=0; 5 long long ans=0; 6 void add(int x,int l,int r,int p,int h) 7 { 8 if(l==r) 9 { 10 c[p]++; 11 ans+=h; 12 return; 13 } 14 int mid=(l+r)>>1; 15 if(mid>=x) 16 add(x,l,mid,p<<1,h+c[p]-c[p<<1]); 17 else 18 add(x,mid+1,r,(p<<1)+1,h); 19 c[p]=c[p<<1]+c[(p<<1)+1]; 20 } 21 int main() 22 { 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++) 25 { 26 scanf("%d",&a[i]); 27 maxn=max(maxn,a[i]); 28 } 29 for(int i=1;i<=n;i++) 30 add(a[i],1,maxn,1,0); 31 cout<<ans<<endl; 32 return 0; 33 }