归并求逆序对
归并求逆序对 是分治的一个经典例子。
简述算法:
利用归并把序列对半分,在一般的归并过程中,我们在前后两部分各设两个指针,按照大小顺序合并成一个序列。
我们要做的就是在这个过程中记录逆序对个数,什么情况下会有逆序对呢?
无非是在前面的数比在后面的数大(翻译过来:在前半部分的数比在后半部分的数大)
设前半部分的指针为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;
来源:https://www.cnblogs.com/Amaris-diana/p/11315075.html