逆序数

树状数组求逆序数的原理

橙三吉。 提交于 2020-03-30 09:13:13
求逆序数的方法有很多,比如归并排序,但本文重点讲一下如何用树状数组来求逆序数。 当数据的范围较小时,比如maxn=100000,那么我们可以开一个数组c[maxn],来记录前面数据的出现情况,初始化为0;当数据a出现时,就令c[a]=1。这样的话,    欲求某个数a的逆序数,只需要算出在当前状态下c[a+1,maxn]中有多少个1,因为这些位置的数在a之前出现且比a大。但是若每添加一个数据a时,就得从a+1到     maxn搜一遍,复杂度太高了。树状数组却能很好的解决这个问题,同样开一个数组d[maxn],初始化为0,d[i]记录下i结点所管辖范围内当前状态有多少个数;当添加数    据a时,就向上更新d,这样一来,欲求a的逆序数时,只需要算sum(maxn)-sum(a);sum(i)表示第i个位置之前出现了多少个1.     举个例子:有5个数,分别为5 3 4 2 1,当读入数据a=5时,c为:0,0,0,0,1;d为:0,0,0,0,1;当读入数据a=3时,c为:0,0,1,0,1;d为:0,0    1,1,1;当读入数据a=4时,c为:0,0,1,1,1;d为:0,0,1,2,1;…………。 此思想的关键在于,读入数据的最大值为maxn,由于maxn较小,所以可以用数组来记录状态。当maxn较大时,直接开数组显然是不行了,这是的解决办法就是离散   化。所谓离散化

Enemy is weak 树状数组

谁说我不能喝 提交于 2020-03-26 04:13:07
来源: http://codeforces.com/problemset/problem/61/E 题意:给你一些数,让求满足i < j < k 且num[i] > num[j] > num[k]的序列的个数,而且已知每个数都是不同的。 思路:这是CF上的一道题,由题意很容易联想到逆序数。实际上就是这样,这道题就是和逆序数有关。假如所给的序列为10 8 3 1,那么我们求出每个数的后面比其小的有多少个,对于该序列来说的话为3,2,1,0。然后我们再求出每个数前面有几个比其大的,对于 该序列来说是0,1,2,3。现在我们把对应的比其小的数的个数和比其大的数的个数相乘再相加就是所求的答案。 现在问题来了,用什么求逆序数。由于最多有100万个数,因此普通的方法求逆序数肯定超时。对于很多数求逆序数,一般有两种方法,归并排序或者是用树状数组求。我是用树状数组求得逆序数。先来说一下什么是树状数组。 树状数组,顾名思义,就是一个数组,但是该数组和普通数组的区别在于,此数组是树状的。树状的含义就是含有节点,该结点所含有的信息和普通数组不同。我们先来考虑普通数组,num[1],num[2],num[3],,,普通数组里的每个元素所含的值就是其本身,而树状数组则不同。num1[1]所包含的元素是其自身,num1[2]所包含的元素是普通num[1]+num[2]的和,num1[3]所包含的元素是num

全排列算法--递归实现(Java)

我的梦境 提交于 2020-03-20 11:06:00
求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现。 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件。以[1, 2]为例 首先展示一下主要代码(完整代码在后面),然后简述   //对数组array从索引为start到最后的元素进行全排列 public void perm(int[]array,int start) { if(start==array.length) { //出口条件 for(int i=0;i<array.length;i++) { // this.result[row][i] = array[i]; System.out.print(array[i]+" "); } // System.out.print(++this.row+": "); // System.out.println("逆序数是:"+ this.against(array)); System.out.print('\n'); } else { for(int i=start;i<array.length;i++) { swap(array,start,i); //交换数组array中索引为start与i的两个元素 perm(array,start+1); swap(array,start,i); } } } 首先数组[1, 2]分析

python实现克莱姆法则

拟墨画扇 提交于 2020-03-05 20:25:55
文章目录 首先完成python模拟行列式运算 公式分析 模块分析与实现 环境 模块导入 全排列 逆序数 方阵计算 克莱姆法则 *Cramer's rule* 注:本文对numpy对象使用append方法时均使用了深拷贝deepcopy,因为python中对象的赋值是按引用传递的,如果不使用深拷贝在append时会改变原有对象从而覆盖原先的值 首先完成python模拟行列式运算 ∣ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a n 1 a n 2 ⋯ a n n ∣ = ∑ ( − 1 ) t a 1 p 1 a 2 p 2 ⋯ a n p n \begin{vmatrix} {a_{11}}&{a_{12}}&{\cdots}&{a_1n}\\ {a_{21}}&{a_{22}}&{\cdots}&{a_2n}\\ {\vdots}&{\vdots}&{\ddots}&{\vdots}\\ {a_{n1}}&{a_{n2}}&{\cdots}&{a_{nn}}\\ \end{vmatrix}= \sum{(-1)^{t}}{a_{1p_{1}}a_{2p_{2}}}{\cdots}{a_{np_{n}}} ∣ ∣ ∣ ∣ ∣ ∣ ∣ ∣ ∣ ​ a 1 1 ​ a 2 1 ​ ⋮ a n 1 ​ ​ a 1 2 ​ a 2 2 ​ ⋮

使用一个函数输出一个整数的逆序数

淺唱寂寞╮ 提交于 2020-02-17 17:54:22
1、本题要求实现一个求整数的逆序数的简单函数。 函数接口定义:int reverse( int number ); 其中函数reverse须返回用户传入的整型number的逆序数。 裁判测试程序样例: #include <stdio.h> int reverse( int number ); int main() { int n; scanf("%d", &n); printf("%d\n", reverse(n)); return 0; } # include <stdio.h> # include <windows.h> # pragma warning(disable:4996) int reverse ( int number ) { int sum = 0 ; int result = 0 ; if ( number < 0 ) //number为负数时只需当成正数一样看待 { printf ( "-" ) ; number = number * ( - 1 ) ; } while ( number ) { result = number % 10 ; sum = sum * 10 + result ; number = number / 10 ; } return sum ; } int main ( ) { int n ; scanf ( "%d" , & n ) ;

归并算法经典应用——求解逆序数

纵饮孤独 提交于 2020-02-13 08:27:03
本文始发于个人公众号: TechFlow ,原创不易,求个关注 在之前介绍线性代数行列式计算公式的时候,我们曾经介绍过逆序数:我们在列举出行列式的每一项之后,需要通过逆序数来确定这一项符号的正负性。如果有忘记的同学可以回到之前的文章当中复习一下: 线性代数行列式 如果忘记呢,问题也不大,这个概念比较简单,我想大家很快就能都搞清楚。 今天的这一篇文章,我想和大家聊聊逆序数的算法,也是一道非常经典的算法题,经常在各大公司的面试题当中出现。 我们先来回顾一下逆序数的定义,所谓逆序数指的是数组当中究竟存在多少组数对,使得排在前面的数大于排在后面的数。我们举个例子,假设当下有一个数组是: [1, 3, 2]。 对于数对(3, 2)来说,由于3排在2前面,并且3 > 2,那么就说明(3, 2)是一对逆序数对。整个数组当中所有逆序数对的个数就是逆序数。 我们从逆序数的定义当中不难发现,逆序数其实是用来衡量一个数组有序程度的一个指标。逆序数越大,说明这个数组递增性越差。如果逆序数为0,说明这个序列是严格递增的。如果一个长度为n的数组的逆序数是 \(C_n^2\) ,那么说明这个数组是严格递减的,此时逆序数最大。 那么,我们怎么快速地求解逆序数呢? 暴力解法 显然,这个问题可以暴力求解,我们只需要遍历所有的数对,然后判断是否构成逆序即可,最后累加一下所有逆序数对的个数就是最终的答案。

原来--“线性代数---行列式”---可以这样子理解。关注我的公众号,我的排版在公众号会好点~~

蓝咒 提交于 2020-01-26 18:19:44
不好意思,这一篇原来事先是在微信公众号上编辑的,有很多排版在这里显示不了,我也是第一次在网上发表文章的小白,我是一名刚上大一学软件的小白,如果感兴趣可以关注一下我的微信公众号,希望能够有各位大佬带带我这个刚上大学的小白在写博客方面飞起来,如果有和我一样的小白也希望在微信公众号上加我好友,一起讨论计算机和数学方面的知识,嘻嘻~~~ 今天的知识点清单 二阶行列式 主、次对角线 对角线展开法 排列 逆序 逆序数 逆序数的计算方法 对换 奇偶排列 n阶行列式的展开项 行列式的特殊题型 二阶行列式 二阶行列式的个人理解: 二阶行列式指4个数组成的符号,也就是2行、2列、一共是4个元素。 二阶行列式是由二元一次方程组推导出来的,是有证明过程的,下面我们就来看看这些二阶行列式是怎样推导出来的。 二阶行列式的推导: 先随便设一组二元一次方程组: 现在我们想要消去未知量X,步骤是“通分”: 最终可以解出Y的结果表达式: 同理,对于解X的结果表达式: 嘻嘻,看出啥规律了没有? 对于上面的解二元一次方程组的过程有这样的规律: 现在我们来聊一聊这个| |是个什么意思: | |是表示行列式的意思,按照我的理解,它的结果是一个值,那么| |就应该是一个计算过程或说是一种计算规则。 二阶行列式的计算规则: 为了能够更好地理解这个计算规则,下面举一个生动的例子: 我觉得这个例子非常适合理科生的表白,嘻嘻!

归并排序应用-----求逆序数

风流意气都作罢 提交于 2020-01-23 20:10:55
归并排序是冒泡排序的一种升级版排序,其灵魂是分治思想,在二分的基础上进行排序,可以将原来时间复杂度为O(n^2)的冒泡排序降低为O(nlogn)的归并排序。 下面我们先来看归并排序,之后再来讲归并排序的应用—求逆序数 归并排序 前面提到,归并排序采用的是二分思想,我们先把一段需要排序的序列分成两半,是不是每一段的交换次数就会变少,然后我们又将分成的两段,继续分成四段,以此类推,直到分到每一段只有一个数的时候,就可以停止,接下来就是分治的–“治” 我们把它们拆开之后,就依次合上来,原来一个数合成两个数,在合的时候又进行比较大小,这样效率会提高很多,最终实现整个序列的排序。 看这张图,可以更好的理解: 下面看一下具体的代码实现 int gb [ 100001 ] ; //临时数组 void mers ( int * a , int s , int mid , int end ) //治(合) { int k = s ; int i = s , j = mid + 1 ; while ( i <= mid && j <= end ) { if ( a [ i ] <= a [ j ] ) { gb [ k ++ ] = a [ i ] ; i ++ ; } else { gb [ k ++ ] = a [ j ] ; j ++ ; } } while ( i <= mid ) { gb

逆序数对 不会做。。。

前提是你 提交于 2020-01-19 12:10:40
代码:::::::::; #include <iostream> #include <cstdio> #include <cstring> using namespace std; int a[100100],n,b[100100]; long long sum=0; void msort(int left,int right) { if(left>=right) return; int mid=(left+right)/2; msort(left,mid); msort(mid+1,right); int i=left,j=mid+1,k=left; while(i<=mid&&j<=right) { if(a[i]>a[j]) { b[k++]=a[j++]; sum+=mid-i+1; } else b[k++]=a[i++]; } while(i<=mid) b[k++]=a[i++]; while(j<=right) b[k++]=a[j++]; for(i=left;i<=right;i++) a[i]=b[i]; } int main() { int i,j; cin>>n; for(i=1;i<=n;i++) cin>>a[i]; msort(1,n); cout<<sum<<endl; return 0; } 来源: CSDN 作者: weixin

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

允我心安 提交于 2020-01-15 06:35:27
归并排序求逆序数 Time Limit: 7000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 9 1 0 5 4 , Ultra-QuickSort produces the output 0 1 4 5 9 . Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence. Input The input contains several test cases. Every test case begins with a line