翻译过来就是有关逆序对问题的专题。

因为大胆报名担任学校专题讲师所以跪着也要准备好课件...那什么是逆序对?

逆序对就是序列中ai>aj且i<j的有序对

举个栗子:

     

其中,5>4,但是5的下标小于4,所以5 4是一对逆序对,同理还有:


共11对逆序对。

现在“愚蠢”的出题人让你求一下给定的数组[maxn]有几对逆序对,这就是经典的逆序对问题了。

题解一:归并排序

归并排序是上万种排序方法中的一种,复杂度为稳定的nlog(n)

应用的方法是分治的思想。

图片引自:https://www.cnblogs.com/chengxiao/p/6194356.html

这就是千奇百怪的排序方式之一:归并排序的思路

#include<iostream>
using namespace std;
const int maxn=,INF=0x3f3f3f3f;
int L[maxn/+],R[maxn/+];
void merge(int a[],int n,int left,int mid,int right)
{
int n1=mid-left,n2=right-mid;
for(int i=;i<n1;i++)
L[i]=a[left+i];
for(int i=;i<n2;i++)
R[i]=a[mid+i];
L[n1]=R[n2]=INF;
int i=,j=;
for(int k=left;k<right;k++)
{
if(L[i]<=R[j])
a[k]=L[i++];
else
a[k]=R[j++];
}
}
void mergesort(int a[],int n,int left,int right)
{
if(left+<right)
{
int mid=(left+right)/;
mergesort(a,n,left,mid);
mergesort(a,n,mid,right);
merge(a,n,left,mid,right);
}
}
int main()
{
int a[maxn],n;
cin>>n;
for(int i=;i<n;i++)
cin>>a[i];
mergesort(a,n,,n);
for(int i=;i<n;i++)
{
if(i)
cout<<" ";
cout<<a[i];
}
cout<<endl;
return ;
}

那这跟逆序对有什么关系呢。

其实归并排序只需要加一行代码就能代表逆序对数目

因为LA数组插入到A数组时,B数组剩下的所有都是符合逆序对标准的项

#include<stdio.h>
#include<string.h>
#define MAX 2100000000
int lef[],rig[];
int i,j,k,ans=,n,a[]={};
void merge(int left,int mid,int right){
int n1=mid-left+;
int n2=right-mid;
for(int i=;i<=n1;i++){
lef[i]=a[left+i-];
}
for(int i=;i<=n2;i++){
rig[i]=a[mid+i];
}
lef[n1+]=;
rig[n2+]=;
int i=,j=;
for(int k=left;k<=right;k++)
{
if(lef[i]<=rig[j]){
a[k]=lef[i++];
}else{
ans+=n1-i+;
a[k]=rig[j++];
}
}
return ;
}
void merge_sort(int p,int r)
{//排序
if(p<r)//元素>1
{
int mid=(p+r)/;
merge_sort(p,mid);
merge_sort(mid+,r);
merge(p,mid,r);
}
return;
}
int main(void)
{
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
merge_sort(,n);
printf("%d",ans);
return ;
}

逆序对的朴素算法是从1开始到n-1结束,复杂度约为n*(n-1)/2,而归并排序是稳定的二分nlog(n)

题解二:Upper_Bound

什么是upper_bound?

upper_bound简单来说也是基于二分思想的查找,返回值是被查序列中第一个大于被查项的指针

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int n;
vector<int> shu;
int main(){
scanf("%d",&n);
long long s=,a;
int kk[];
for(int i=;i<n;i++){
scanf("%d",&kk[i]);//核心代码:
s+=shu.end()-upper_bound(shu.begin(),shu.end(),kk[i]);
shu.insert(upper_bound(shu.begin(),shu.end(),kk[i]),kk[i]);
}
printf("%d",s);
return ;
}

最新文章

  1. unity3d 免费好用的数据库处理框架 数据库直连框架
  2. PHP ServerPush (推送) 技术的探讨
  3. 《HTML5秘籍》学习总结--2016年7月24日
  4. Java开发心得
  5. td
  6. 2016沈阳网络赛 odd-even number
  7. NodeJS 框架一览
  8. 在Visual Studio 2012中使用GSL
  9. 在Rancher 1.6上部署Traefik负载均衡器
  10. Mimikatz 法国神器
  11. Confluence 6 数据库结构图
  12. 【托业】新托业全真题库---TEST1
  13. VirtualBox 扩展包卸载或安装失败(VERR_ALREADY_EXISTS)(转)
  14. Py中enumerate方法【转载】
  15. C/C++基础---算法概览
  16. go实现的简易TCP的客户端和服务器
  17. HDU3629(凸四边形的个数)
  18. 快速入门:十分钟学会PythonTutorial - Learn Python in 10 minutes
  19. WPF 组织机构下拉树多选,递归绑定方式现实
  20. ios UITableView中Cell重用机制导致内容重复解决方法

热门文章

  1. python Python程序的架构
  2. oracle-Immediate
  3. Laravel 登录后清空COOKIE 方法
  4. Symmetric Tree 深度优先搜索
  5. OpenCV在各版本上的安装教程
  6. HDU_1061:Rightmost Digit
  7. poj 3107 Godfather 求树的重心【树形dp】
  8. 【Pandas】Pandas求某列字符串的长度,总结经验教训
  9. C# POST 表单发送文件
  10. ORACLE内部操作