洛谷 P1908 逆序对 Label:归并排序||树状数组

Posted Radiumlrb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1908 逆序对 Label:归并排序||树状数组相关的知识,希望对你有一定的参考价值。

题目描述

猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

输入输出格式

输入格式:

 

第一行,一个数n,表示序列中有n个数。

第二行n个数,表示给定的序列。

 

输出格式:

 

给定序列中逆序对的数目。

 

输入输出样例

输入样例#1:
6
5 4 2 6 3 1
输出样例#1:
11

说明

对于50%的数据,n≤2500

对于100%的数据,n≤40000。

代码:解法一

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int N,a[100005],temp[100005],cnt;
 7 
 8 void print(){
 9     for(int i=1;i<=6;i++){
10         printf("%d ",a[i]);
11     }
12     puts("");
13 }
14 
15 void merge_sort(int l,int r){
16     if(l>=r) return;
17     int mid=(l+r)>>1;
18     merge_sort(l,mid);merge_sort(mid+1,r);
19     
20     
21     int i=l,j=mid+1,point=l;
22     while(i<=mid&&j<=r){
23         if(a[i]>a[j]){
24             temp[point++]=a[j++];
25             cnt+=(mid-i+1);
26         }
27         else{
28             temp[point++]=a[i++];
29         }
30     }
31     
32     while(i<=mid) temp[point++]=a[i++];
33     while(j<=r)   temp[point++]=a[j++];
34     
35     for(int k=l;k<=r;++k)
36         a[k]=temp[k];
37 //    print();
38 }
39 
40 int main(){
41 //    freopen("01.txt","r",stdin);
42     
43     scanf("%d",&N);
44     for(int i=1;i<=N;++i)
45         scanf("%d",&a[i]);
46     
47     merge_sort(1,N);
48     
49     printf("%d\n",cnt);
50     return 0;
51 }

 

暴力枚举的话,可以过两个点~

转载题解如下:http://blog.csdn.net/acdreamers/article/details/16849761

归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。

在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在

前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并

排序中的合并过程中计算逆序数.

以上是关于洛谷 P1908 逆序对 Label:归并排序||树状数组的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1908 求逆序对 [归并排序]

归并排序+归并排序求逆序对(例题P1908)

P1908 逆序对-(cdq分治)

逆序对+离散树状数组+。。。。

P1908 逆序对——归并算法

P1908 逆序对