wikioi 1688 求逆序对
/*=========================================================== wikioi 1688 求逆序对 时间限制: 1 s 空间限制: 128000 KB题目描述 Description给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目.数据范围:N<=105。Ai<=105。时间限制为1s。输入描述 Input Description第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。 输出描述 Output Description所有逆序对总数. 样例输入 Sample Input 4 3 2 3 2 样例输出 Sample Output 3注解:题目考察分治法。解决该题需要用到二路归并排序。 假如本题直接使用两重for循环来模拟,则最后肯定是会超时的。模拟的Pascal代码如下:ans:=0;read(n);for i:=1 to n do read(a[i]);for i:=1 to n-1 dofor j:=i+1 to n doif a[i]>a[j] then ans:=ans+1;writeln(ans); 这个模拟算法是O(n^2)的算法,所以无法解决N<=10^5这样规模的问题。 其实从这个模拟的过程来看,终归是要把序列当中的所有数做两两比较。联想到冒泡之类的排序也是要比较的。所以,随便找一个排序算法稍作修改, 应该就可以解决问题了。但是,冒泡、选择和直接插入排序都是O(n^2)算法。这样的算法并未能提高程序的效率。相反,浪费脑细胞去修改算法。 排序算法里面的二路归并排序倒是不错的选择,因为它的时间复杂度是O(n*lg(n))。 =============================================================*/
1 #include<stdio.h> 2 3 int n,a[1000100],t[1000010]; 4 long long ans=0; 5 6 void merge_sort(int A[],int l,int r,int T[]) 7 { 8 if(l<r) 9 { 10 int m=l+((r-l)>>1); 11 int x=l,y=m+1,i=l; 12 merge_sort(A,l,m,T); 13 merge_sort(A,m+1,r,T); 14 while(x<=m||y<=r) 15 { 16 if(y>r || (x<=m && A[x] <= A[y])) T[i++]=A[x++]; 17 else {T[i++]=A[y++];ans+=(m-x+1);} 18 } 19 for(i=l;i<=r;i++) A[i]=T[i]; 20 } 21 } 22 23 24 int main() 25 { 26 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 29 merge_sort(a,1,n,t); 30 printf("%lld\n",ans); 31 return 0; 32 }
View Code
另一段代码:
1 #include <stdio.h> 2 3 int n,a[1000100],t[1000010]; 4 long long count=0; 5 6 void merge_sort(int *a,int x,int y,int *t);//对a[]在[x,y) 下标范围的元素进行归并排序 7 8 int main(int argc, char *argv[]) 9 { 10 scanf("%d",&n); 11 for(int i=0;i<n;i++) scanf("%d",&a[i]); 12 merge_sort(a,0,n,t); 13 printf("%lld\n",count); 14 return 0; 15 } 16 void merge_sort(int *a,int x,int y,int *t)//对a[]在[x,y) 下标范围的元素进行归并排序 17 { 18 if(y-x>1) 19 { 20 int m=x+(y-x)/2; 21 int p=x,q=m,i=x; 22 merge_sort(a,x,m,t); 23 merge_sort(a,m,y,t); 24 while(p<m||q<y) 25 { 26 if( q>=y || (p<m&&a[p]<=a[q]) ) t[i++]=a[p++]; 27 else { t[i++]=a[q++]; count=count+m-p; } 28 } 29 for(i=x;i<y;i++) a[i]=t[i]; 30 } 31 }
注意:在统计逆序对数目的时候,不要重复统计。
转载于:https://www.cnblogs.com/huashanqingzhu/p/4185292.html
wikioi 1688 求逆序对相关推荐
- codevs1688 求逆序对(权值线段树)
1688 求逆序对 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 给定一个序列a1,a2,-,an,如 ...
- szu 寒训第二天 树状数组 二维树状数组详解,以及树状数组扩展应用【求逆序对,以及动态第k小数】
树状数组(Binary Index Tree) 树状数组可以解决可以转化为前缀和问题的问题 这是一类用以解决动态前缀和的问题 (有点像线段树简版) 1.对于 a1 + a2 + a3 + - + an ...
- Tido 习题-二叉树-树状数组求逆序对
这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述 样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示 #include<iostre ...
- 归并排序模板(附求逆序对)
逆序对满足两个条件, i < j 和 ai > aj 归并可以求逆序对, 因为是按顺序加入, 所以右区间加入的时候, 左区间的数满足 i < j, 然后左边还没有加入的数肯定比当前的 ...
- P3531 [POI2012]LIT-Letters(求逆序对)
题目传送门:https://www.luogu.com.cn/problem/P3531 题意 给出只包含大写字母的字符串 A 和字符串 B,每次可以交换字符串 A 两个相邻的字符,求 A 变成 B ...
- hust1347(归并排序求逆序对)
题意: 给出一个数列,你要对这个数列的数字进行k次交换操作,使得交换之后的数列逆序对虽少. 思路: 求原数列的逆序对,再和k比就行了.求逆序对要用归并排序,因为树状数组开不下. 代码: #includ ...
- 树状数组求逆序对_区间和的个数(树状数组)
327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...
- 用不同的姿势求逆序对(复习篇)
用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...
- CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)
题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a,现在要求选出一个 x,将 a 中的每个元素都异或之后得到一个新的数列 b,要求数列 b 的逆序对最小,问最小的逆序对是多少,x 该如何选择 ...
最新文章
- 智能车竞赛技术报告 | 智能车视觉 - 温州大学- 春华秋实
- 用python绘图_用python绘图
- 链路层的封装方式与IP选路 (二)
- 浏览器中关于事件的那点事儿
- 高并发来袭,面向Google编程的程序员要小心了!
- WPF Logical Tree vs. Visual Tree
- mysql如何创建日志_mysql中的日志
- 2013.01.16 Python的面向对象编程
- 协程asyncio_迭代器,生成器,协程
- mac 删除文件夹里所有的.svn文件
- SAP Smartform转成PDF方法汇总
- 海康sdk java_java调用海康sdk案例
- Kylin多维分析引擎(四):Kylin Cude构建流程详解
- 右键菜单项删除 pycharm vs
- 7.用户登陆,用户退出,记住用户名和密码
- 谷歌掐架甲骨文:揭秘Java侵权案始末
- JS 全屏和退出全屏--requestFullScreen详解及兼容代码
- 几种比较好看的颜色代码
- 工控安全:攻防演示案例分享
- 清明节到来,微信公众号图文排版有哪些使用技巧?