sgu-180 Inversions 裸题:求逆序对个数
来源:互联网 发布:法医秦明网络剧百度云 编辑:程序博客网 时间:2024/05/23 10:34
题目大意:
给你一个n,和n个数a1....an,请你求出这个序列的逆序对个数,n<=65537,ai<=1e9
解题思路:
首先,O(n^2)的做法我就不多说了,不会写的跪键盘吧。。。。。。
但是对与n的数据大小,显然过不了(其实是我没去想,如果认为过的了得请自己试,但是我们是有追求的人),所以我们需要用到O(nlogn)的做法。
相信大家都有一定了解,就是用归并排序来完成对逆序对的查找。
那么具体如何实现呢?其实很简单:
首先归并排序大家总会吧(不会的我也没办法,因为我也不会。。。。)
我们都知道归并排序中有一个对两个有序的序列合并的操作,我们就是要利用这个操作来求逆序对。
首先我们假设两个有序的序列为b1,b2,假设序列b1在序列b2前面,那么我们就只需要求出b1与b2的逆序对的个数就行了。
这其实是用到了分治的思想,显然数列内部的不需要考虑了,因为我们求出这两个数列的时候已经求出了序列内部的逆序对个数了。
我们发现b1,b2已经是有序的了,所以对于b2[ j ]当我们找到一个最小的b1[ i ]使得b2[ j ]<b1[ i ],那么从i到b1的最后一个元素都可以与b2[ j ]组成逆序对,所以我们只需要在合并时,若b2[ j ]加入合并的数组,这是b1下标为i,那么逆序对个数就应该加入从i到b1数组的最后一个元素的个数,这样我们就可以再归并排序的时候就可以求出逆序对了。
附上代码:
#include <stdio.h>//我是淳朴的C党int n,a[66000]={0};long long sum=0;int b[66000]={0};void done(int l,int r){int i,j,p;int mid=(l+r)/2;if(l>=r)return;done(l,mid);done(mid+1,r);for(i=l,j=mid+1,p=l;i<=mid && j<=r;){if(a[i]<=a[j])b[p++]=a[i++];else{b[p++]=a[j++];sum+=mid-i+1;}}for(;i<=mid;)b[p++]=a[i++];for(;j<=r;)b[p++]=a[j++];for(i=l;i<=r;i++)a[i]=b[i];return;}int main(){int i;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d",&a[i]);done(1,n);printf("%I64d\n",sum);return 0;}
0 0
- sgu-180 Inversions 裸题:求逆序对个数
- SGU 180 Inversions(树状数组求逆序对)
- SGU 180-Inversions(树状数组离散化求逆序对数)
- SGU 180 Inversions 逆序数
- SGU 180 Inversions ( 逆序对(卡数据范围))
- SGU 180 - Inversions(逆序数)
- SGU 180. Inversions(归并排序求逆序数)
- 【SGU】180. Inversions(归并排序求逆序数)
- Count Inversions in an array (求数组中的逆序对个数)
- 【SGU 180】Inversions —— 归并排序或树形数组计算逆序对
- 求逆序对个数
- 逆序数poj 2299 Ultra-QuickSort sgu 180 Inversions
- sgu 180 Inversions
- SGU 180 Inversions
- SGU 180 Inversions
- SGU 180 Inversions
- 求数组逆序对个数
- 求逆序对的个数
- SGU 106 扩展欧几里得
- Quartz2D 图像处理
- leetcode:Valid Palindrome 合法回文
- android背景平铺方式 tileMode
- dispatchTouchEvent & onTouchEvent & onInterceptTouchEvent
- sgu-180 Inversions 裸题:求逆序对个数
- leetcode Min Stack
- 使用svnsync实现版本库的同步备份
- ActivityGroup切换不用每次加载视图
- BZOJ 3439 Kpm的MC密码 Trie树+可持久化线段树
- [algorithm,c++] 基于c++的二维k-means代码实现
- vs2010打开时遇到的问题
- 第十二周项目三(6):汉诺塔
- 解决Rocketdock在win7上重启后不能保存设置和图标的问题