hdu 4911 “Inversion”——逆序对问题
题目描述
bobo has a sequence a 1,a 2,…,a n. He is allowed to swap two adjacent numbers for no more than k times.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and a i>aj.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
Output
For each tests:
A single integer denotes the minimum number of inversions.
Sample Input
3 1
2 2 1
3 0
2 2 1
Sample Output
1
2
分析:
关键是找到大的数排在小的数的前面。
这道题如果使用暴力的搜索,太过复杂而且基本上肯定会TLE的。
归并排序是利用了递归思想,每个子序列都是有序的,因此逆序的情况一定是发生在不同的序列之间的,然后在做归并的过程中自然是需要不同序列间的数判断大小关系的,在判断大小关系的过程中就可以找到逆序对了,因此这考虑用归并排序的思想。
先考虑交换0次即k=0的情况:
(1)子序列内一定不存在逆序对;
(2)子序列之间做合并,假设某一层递归出的两个子序列分别为:
[13 94 99],[34 56],从这里就可以看出逆序不止一个,34和94,99之间都存在逆序。
因此只需要在归并排序过程中记录逆序对就好了。
再考虑k≠0的情况,即把序列中任意两个相邻数交换不超过k次的逆序对最少有多少,注意是不超过k次,并不一定就要交换k次,原始序列的逆序对个数cnt可以在归并排序中记录下来,因此接下来对k分两类情况考虑:
(1)若cnt<=k,即逆序对的总数不足以交换k次。所以进行k次交换之后,最少的逆序对数一定为0.
(2)若cnt>k,让k次交换都发生在逆序的相邻数上面,那么剩余的逆序对就是cnt-k次。
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100005],b[100005],cnt;
void Merge(ll l,ll mid,ll r){//归并排序ll i=l,j=mid+1,t=0;while(i<=mid&&j<=r){if(a[i]>a[j]){//存在逆序对b[t++]=a[j++];cnt+=mid-i+1;//既然子序列都是有序的,该子序列后面的数也一定和a[j]后面的数逆序}else b[t++]=a[i++];}//可能只处理完一个子序列的,另一个序列剩下的直接添加while(i<=mid)b[t++]=a[i++];while(j<=r)b[t++]=a[j++];for(i=0;i<t;i++)a[l+i]=b[i];//把排序好的b[]复制回a[]
}
void Mergesort(ll l,ll r){if(l<r){ll mid=(l+r)/2;Mergesort(1,mid);Mergesort(mid+1,r);Merge(l,mid,r);//要注意递归的细节,子序列先归并}
}
int main(){ll n,k;while(~scanf("%lld%lld",&n,&k)){cnt=0;for(ll i=0;i<n;i++)scanf("%lld",&a[i]);Mergesort(0,n-1);if(cnt<=k)printf("0\n");else printf("%I64d\n",cnt-k);}
}
hdu 4911 “Inversion”——逆序对问题相关推荐
- hdu 4911 求逆序对数+树状数组
http://acm.hdu.edu.cn/showproblem.php?pid=4911 给定一个序列,有k次机会交换相邻两个位置的数,问说最后序列的逆序对数最少为多少. 实际上每交换一次能且只能 ...
- Count Inversion逆序对数问题
逆序对数问题Count Inversion Problem Description Recall the problem of finding the number of inversions. As ...
- HDU 4911 Inversion 树状数组求逆序数对
显然每次交换都能降低1 所以求出逆序数对数,然后-=k就好了.. . _(:зゝ∠)_ #include<stdio.h> #include<string.h> #includ ...
- hdu 5493 Queue(逆序对,线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5493 解题思路: 一道线段树的题目,因为是前面或者后面有k个比自己高的人,所以我们应该按照由身高从小到 ...
- HDU 4911 Inversion - 疯狂的癫子 解题心得
原题: Description bobo has a sequence a 1,a 2,-,a n. He is allowed to swap two adjacent numbers for no ...
- HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911 解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少 ...
- Minimum Inversion Number HDU - 1394(求一个数字环的逆序对+多种解法)
题意: 给出n个数(0~n-1,每个数仅出现一次),问它长为n的循环序列中逆序对最少的数量. 多种解法:暴力+树状数组+分治+规律推导公式 题目: The inversion number of a ...
- UVA 11990 ``Dynamic'' Inversion 动态逆序对
``Dynamic'' Inversion Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/index ...
- HDU - 5592 ZYBs Premutation(线段树,逆序对)
题目链接:点击查看 题目大意:给出 n 个数,分别表示数列 p 前缀 [ 1 , i ] 的逆序对个数,现在要求还原数列 p 题目分析:设 a[ i ] 为前缀 [ 1 , i ] 的逆序对个数,则 ...
- 线段树求逆序对(hdu1394Minimum Inversion Number)
说实话,线段树求逆序对我理解了半天诶,不知是否有人像我一样. 对于每个数来说,只有和已经出现过的.比它大的数才能形成逆序对,那么在给定的数列中,每给一个数就向前找比它大的数. 样例:10 1 3 6 ...
最新文章
- python创建文件os_Python之文件与目录操作(os、zipfile、tarfile、shutil)
- opnet中的例子模型
- Android Studio 分析器详解
- mysql主从同步-问题梳理
- Mysql8.0 的sql修改成 Mysql7.X的sql
- 程序员的进阶课-架构师之路(2)-数组
- 通俗易懂地理解并发和并行的区别
- Himall商城普通帮助类(二)
- 电商项目——商品分类/品牌查询
- Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean
- K线形态识别—三K线之卖出型三日K线组合
- H5 - 实现半颗星评分功能
- 【电子电路】ADC芯片如何选型
- echarts使用e_macarons方法
- jzoj 6012.【NOIP2019模拟1.25A组】荷马史诗 dp
- aicloud服务器不稳定,华硕AC级无线路由器搭载AiCloud上市
- word段落居中的快捷键_word里段落的快捷键 WORD中段落的快捷键是什么
- なな : 动态jianmo
- 山建大计算机学院,山建大丨历数20年来建大学生作业设计表达的前世今生
- nodejs gm 中文 linux,nodejs图片处理工具gm用法
热门文章
- finalize()与PhantomReference学习笔记
- oracle创建用户和表空间,授权,oracle用imp导入dmp文件
- php 通过 create user 和grant 命令无法创建数据库用户和授权的解决办法
- ASP.NET中 CompareValidator(比较验证)的使用
- CDC不同模式在ODI体现系列之二 异步模式
- 8大排序算法图文解说
- 第10章 接口、继承与多态----对象类型的转换
- Mbs Framework 简介
- 从AssetBundle中获取图片,给Image 组件替换Sprite
- linux查看挂载内存卡,Ubuntu Linux 挂载移动硬盘、U盘、SD卡(对于新手)