洛谷--逆序对
题目描述
猫猫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 2500n≤2500
对于50%的数据,n≤4×104n \leq 4 \times 10^4n≤4×104。
对于所有数据,n≤5×105n \leq 5 \times 10^5n≤5×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 }
大家和我一起加油呀!!!!!!