栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

蓝桥杯练习系统:试题 算法提高 逆序对

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

蓝桥杯练习系统:试题 算法提高 逆序对

试题 算法提高 逆序对

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

SORT公司是一个专门提供排序服务的公司,该公司的宗旨是:“顺序是美丽的”。他们的工作是通过一系列移动,将某些物品按顺序摆好。他们的服务是通过工作量来计算的,即移动物品的次数。所以,在工作前必须先考察工作量,以便向客户提出收费数目。
  用户并不需要知道精确的移动次数,实质上,大多数人都是凭感觉来认定这一列物品的混乱程度。根据SORT公司的经验,人们一般是根据“逆序对”的数目多少来称呼这一序列的混乱程度。假设将序列中第I件物品的参数定义为Ai,那么排序就是将A1,……An从小到大排序。若iAj,则就为一个“逆序对".
  SORT公司请你写一个程序,在尽量短的时间内统计出”逆序对“的数目。
输入格式
  第1行为n(1<=n<=100000)
  接下来N行,每行一个长整数型范围内的整数。
输出格式
  一个整数,为逆序对的数目。
样例输入
5
3
1
4
5
2
样例输出
4

理解

1.逆序对:设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。
2.本题目用归并算法,在每层递归中累加逆序对的数量

提交代码
#include
using namespace std;
const int N=1e6+10;
int a[N],tmp[N];
int merge_sort(int a[],int l,int r){
	if(l>=r)return 0;
	int mid=l+r>>1;
	int ret=merge_sort(a,l,mid)+merge_sort(a,mid+1,r);
	int x=l,y=mid+1,k=0;
	while(x<=mid&&y<=r)
		if(a[x]<=a[y])tmp[k++]=a[x++];
		else {
			tmp[k++]=a[y++];ret+=mid+1-x;
		}
	while(x<=mid)tmp[k++]=a[x++];
	while(y<=r)tmp[k++]=a[y++];
	for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j];
	return ret;
}
	
int main(){
	int n;cin>>n;
	for(int i=0;i>a[i];
	cout< 

但是数据大小有点问题,改成long long ,龙龙这样就过了

#include
using namespace std;
typedef long long ll;
const int N=1e6+10;
int a[N],tmp[N];
ll merge_sort(int a[],int l,int r){
	if(l>=r)return 0;
	int mid=l+r>>1;
	ll ret=merge_sort(a,l,mid)+merge_sort(a,mid+1,r);
	int x=l,y=mid+1,k=0;
	while(x<=mid&&y<=r)
		if(a[x]<=a[y])tmp[k++]=a[x++];
	
		else {
			tmp[k++]=a[y++];ret+=mid+1-x;
		}
	while(x<=mid)tmp[k++]=a[x++];
	while(y<=r)tmp[k++]=a[y++];
	for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j];
	return ret;
}
	
int main(){
	int n;cin>>n;
	for(int i=0;i>a[i];
	cout< 
总结: 

归并算法来源于acwing,算法模板如下:

#include 

using namespace std;

typedef long long ll;//long long比较长写起来比较麻烦,故用typedef

ll merge_sort(int l, int r);//该函数的功能为直接返回逆序对个数

const int N = 1e5 + 10;

int q[N], n, a[N];

int main()
{
    cin >> n;
    
    for (int i = 0; i> q[i];
    
    cout << merge_sort(0, n - 1) <
    if (l == r) return 0;//递归的终点
    
    int mid = l + r >> 1;
    ll count = merge_sort(l, mid) + merge_sort(mid + 1, r);//将左右逆序对数量先加总
    
    int i = l, j = mid + 1, k = 0;
    while(i<=mid && j<=r)
    {
        if (q[i]<=q[j]) a[k++] = q[i++];
        else 
        {
            count = count + (mid + 1 - i);//由上图可知此处右侧每个数能与左侧构成的逆序对有mid + 1 -i个
            a[k++] = q[j++];
        }
    }
    while(i<=mid) a[k++] = q[i++];//扫尾
    while(j<=r) a[k++] = q[j++];//扫尾
    
    for (i = l, k = 0; i<=r;) q[i++] = a[k++];//归还数组元素
    
    return count;//返回逆序对个数
}//该代码引用AcWing网站的代码

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/875708.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号