洛谷--逆序对

题目描述

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

输入格式

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

第二行n个数,表示给定的序列。序列中每个数字不超过10910^9109

输出格式

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

输入输出样例

输入 #1
6
5 4 2 6 3 1
输出 #1
11

说明/提示

对于25%的数据,n≤2500n \leq 2500n2500

对于50%的数据,n≤4×104n \leq 4 \times 10^4n4×104。

对于所有数据,n≤5×105n \leq 5 \times 10^5n5×105

请使用较快的输入输出

应该不会n方过50万吧 


以上就是原题了

但是要怎么做捏?????????

不知道大家还记不记得上学期(我的)DS里面在排序算法(内排序)里面的二路归并排序

归并排序,就是merge_sort,它的核心思想就是分开再合起来(这个是不是分治算法???)

归并排序里面最开始的是一个叫做归并子算法的东西,为的是把相邻的两个有序序列合并为一个有序的序列

康康大神的解释

 

 

 辣我上代码辣!!!!!!!

 1 #include<iostream>
 2 #include<cstdio>
 3 
 4 using namespace std;
 5 
 6 int n,put_in[500010],sorted[500010];
 7 long long ans;
 8 
 9 void merge_sort(int begin, int end)//归并排序
10 {
11     if(begin == end)
12         return;
13 
14     int mid = (begin + end) / 2;
15     int i = begin;
16     int j = mid + 1;
17     int k = begin;
18 
19     merge_sort(begin, mid);
20     merge_sort(mid + 1, end);
21 
22     while(i <= mid && j <= end)
23     {
24         if(put_in[i] <= put_in[j])
25             sorted[k++] = put_in[i++];
26         else
27         {
28             sorted[k++] = put_in[j++];
29             ans += mid - i + 1;
30         }
31     }
32 
33     while(i <= mid)
34         sorted[k++] = put_in[i++];
35 
36     while(j <= end)
37         sorted[k++] = put_in[j++];
38 
39     for(int t = begin;t <= end;t++)
40         put_in[t] = sorted[t];
41 }
42 
43 int main()
44 {
45     scanf("%d",&n);
46 
47     for(int i = 1;i <= n;i++)
48         scanf("%d",&put_in[i]);
49 
50     merge_sort(1, n);
51 
52     printf("%lld",ans);
53     return 0;
54 }

 

 

 

 

posted @ 2019-08-12 19:56  samshui  阅读(284)  评论(0编辑  收藏  举报