码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-08-26 22:39:32      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

题目描述

猫猫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:归并排序||树状数组

标签:

原文地址:http://www.cnblogs.com/radiumlrb/p/5811757.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!