分治题目 wikioi 1688 逆序数组 算导2-4

解题报告

算导上给了提示 用归并排序的代码进行修改来实现 思考后不难看出 归并排序的合并(merge)过程中 对数据进行了比较

1)如果数组L 的当前某元素大于数组R的当前元素,那么 由于L数组是有序的(升序) 因此 L数组当前元素以及他后面的所有元素都与R数组构成逆序对

2)我们的排序并不影响逆序对的数量 因为排序的时候不会改变当前被排序的数据和还未被处理的数据之间的位置关系(就是说 排序前在未处理元素左边的数据,排序后还在未处理元素左边,所以不改变逆序对的数量)

严格的证明待以后学好算法导论再来证,现在只要知道上面两条就可以来处理这道题了

最初的时候 由于把deseq技术变量设为了 int 导致溢出  结果WA了 后来用随机数据测试之后 找到了问题 改为了long long

真的是好久不写题了,连最低级的错误都犯

修改归并排序的merge代码

/*************************************************************************
  > File Name: mergesort.cpp
  > Author: VOID_133
  > QQ: 393952764
  > Mail: [email protected]
  > Created Time: 2014年08月06日 星期三 14时17分16秒
  > Content : Divide and Conquer Classic Problem
  MergeSort
 ************************************************************************/

#include<iostream>
#include<cstdio>
typedef long long LL;
using namespace std;
const int MAX=100000;
int L[MAX];
int R[MAX];
LL deseqnum=0;
void mergesort(int* A,int first,int end);
void merge(int *A,int first,int mid,int end);
void mergesort(int* A,int first,int end)
{
	if(first<end)
	{
		int mid=(first+end)/2;
		mergesort(A,first,mid);
		mergesort(A,mid+1,end);	//Solve the problem recursively
		merge(A,first,mid,end);
	}
	return ;
}

void merge(int *A,int first,int mid,int end)
{
	int lenL=mid-first+1;
	int lenR=end-mid;
	for(int i=1;i<=lenL;i++) L[i]=A[first+i-1];
	for(int i=1;i<=lenR;i++) R[i]=A[mid+i];
	int li=1;
	int ri=1;
	int cnt=first;						//the array we should merge is from A[first] to A[end] so we can only modify these value ,we shouldn‘tmodify other A values
	//The Problem has fixed
	while(li<=lenL && ri <=lenR)
	{
		int tmp;
		if(L[li]>R[ri])
		{
			tmp=R[ri];
			ri++;
			deseqnum+=lenL-li+1;                                //这个代码是后来添加的逆序对计数代码 其余的代码都没有改动
		}
		else
		{
			tmp=L[li];
			li++;
		}
		A[cnt++]=tmp;
	}
	if(li<=lenL)
	{
		while(li<=lenL)
		{
			A[cnt++]=L[li++];
			//deseqnum+=lenR;
		}
		//deseqnum-=lenR;
	}
	while(ri<=lenR)
	{
		A[cnt++]=R[ri++];
	}
	return ;
}

int main(void)
{
	int arr[MAX];
	int n;
	while(	scanf("%d",&n)!=EOF)
	{
		deseqnum=0;
		for(int i=1;i<=n;i++) cin>>arr[i];
		mergesort(arr,1,n);
		//for(int i=1;i<=n;i++) cout<<arr[i]<<" ";
		cout<<deseqnum<<endl;
	}

	return 0;
}

某人的blog这么说:

该算法若将合并数组操作写成循环形式会快百分之二十到三十,因为递归调用函数时会占用额外的时间。

wikiOI的题解上说此题可以用线段树来做ORZ 还有树状数组ORZ   慢慢来吧Orzzzzzzzzzzzzzzzzzzzzzzzzzz

分治题目 wikioi 1688 逆序数组 算导2-4,布布扣,bubuko.com

时间: 2024-10-06 03:58:53

分治题目 wikioi 1688 逆序数组 算导2-4的相关文章

(c++实现)南阳理工acm 题目117 求逆序数

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整

Frosh Week(HDU_3743)归并排序+逆序数对

Frosh Week Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2772    Accepted Submission(s): 923 Problem Description During Frosh Week, students play various fun games to get to know each other a

Ultra-QuickSort--POJ2299(归并排序求逆序数对)

http://poj.org/problem?id=2299 归并排序:比如现在有一个序列[l,r),我们可以把这个序列分成两个序列[l,mid),[mid,r),利用递归按照上 述方法逐步缩小序列,先使子序列有序,再使子序列区间有序,然后再把有序区间合并,很好滴体现了分治的思想. 逆序数(如果有i<j,存在a[i] > a[j],则称a[i]与a[j]为逆序数对) #include<stdio.h> #include<algorithm> #include<ma

《程序设计与算法(二)算法基础》《第五周 分治》求排列的逆序数 11

011:求排列的逆序数 查看 提交 统计 提问 总时间限制:  1000ms 内存限制:  65536kB 描述 在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务. 对于不同的排名结果可以用逆序来评价它们之间的差异.考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序. 一个排列含有逆序的个数称为这个排

【Algorithm】逆序数的分治求解

逆序数的分治求解,时间复杂度O(nlgn).基本思想是在归并排序的基础上加逆序计数. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <ctime> 6 using namespace std; 7 8 #define MAXN 100005 9 10 int a[MAXN], b[MAXN]; 11 in

逆序数 51nod 1019 归并 分治

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4.给出一个整数序列,求该序列的逆序数. Input 第1行:N,N为序列的长度(n <= 50000) 第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9) Output 输出逆序数 Input示例 4 2 4 3 1 Output示例 4 看程序吧 不会讲

HDU 1394 Minimum Inversion Number (树状数组求逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13942    Accepted Submission(s): 8514 Problem Description The inversion number of a given number sequence a1, a2, ..., a

ACM--归并排序&amp;&amp;树状数组--nyoj 117--求逆序数

南阳oj题目地址:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=117 求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组

HDU 6318 Swaps and Inversions 思路很巧妙!!!(转换为树状数组或者归并求解逆序数)

Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2315    Accepted Submission(s): 882 Problem Description Long long ago, there was an integer sequence a.Tonyfang think this se