线段树求逆序对

嘘!这里是逆序对的题目链接

以前一直不知道线段树有求逆序对的功能

之前老师提了一下又刚好没听

今天自己模拟了一遍似乎是对了

代码虽短但耗费的空间却大

而归并排序代码虽然复杂却只耗费少量的空间

大概思想:

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 }
amaing code

 

posted @ 2015-10-24 20:04  HELLO----WORLD  阅读(449)  评论(0编辑  收藏  举报