归并排序求逆序对

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-13 22:24:29

归并求逆序对

 

归并求逆序对 是分治的一个经典例子。

简述算法:
利用归并把序列对半分,在一般的归并过程中,我们在前后两部分各设两个指针,按照大小顺序合并成一个序列。
我们要做的就是在这个过程中记录逆序对个数,什么情况下会有逆序对呢?
无非是在前面的数比在后面的数大(翻译过来:在前半部分的数比在后半部分的数大)
设前半部分的指针为t1,后半部分的指针为t2
如果a[t1] > a[t2],那么t1~mid的元素一定都比t2大,一定都可以与t2形成逆序对:ans+= (mid- t1+ 1)+1

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 const int N=100010;
 8 int a[N],b[N],n,ans=0; 
 9 
10 void merge(int l,int r)
11 {
12     if (l==r) return;
13     int mid=(l+r)>>1;
14     merge(l,mid);
15     merge(mid+1,r);
16     int t1=l; 
17     int t2=mid+1;
18     for (int i=l;i<=r;i++)
19     {
20         if ((t1<=mid&&a[t1]<=a[t2])||t2>r) {
21             b[i]=a[t1];
22             t1++;
23         }
24         else
25         {
26             b[i]=a[t2]; 
27             ans+=(mid-t1+1);
28             t2++;
29         } 
30     }
31     for (int i=l;i<=r;i++) a[i]=b[i];
32 }
33 
34 int main()
35 {
36     scanf("%d",&n);
37     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
38     merge(1,n);
39     printf("%d",ans);
40     return 0;
41 } 

 

end;

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!