FZU2018级算法第五次作业 m_sort(归并排序或线段树求逆序对)
首先对某人在未经冰少允许情况下登录冰少账号原模原样复制其代码并且直接提交的赤裸裸剽窃行为,并且最终被评为优秀作业提出抗议!
题目大意:
给一个数组含n个数(1<=n<=5e5),求使用冒泡排序为递增序列时,最少交换次数为多少次。
题目分析:
对于数组中任意两个数,若$i<j$且$ai>aj$,则ai与aj必然会进行交换使其变为顺序,因此只需要求逆序对数量即可。
分享两种方法,第一种使用归并排序:
对于数组进行递归分治,使用归并排序,在数组两侧合并的过程中,若右侧元素先入数组,则左侧剩余元素均比该元素小,因此可以在归并排序的过程中将逆序对数量求出。
下面分享代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int maxn=5e5+;
int arrcy[maxn],lef[maxn],rig[maxn];
ll ans=; void mergesort(int *,int ,int);
void merge(int *,int ,int,int); int main()
{
int n,i;
scanf("%d",&n);
for (i=;i<n;i++) scanf("%d",&arrcy[i]);
mergesort(arrcy,,n-);
printf("%lld\n",ans);
return ;
} void mergesort(int arrcy[],int l,int r)
{
if(l<r)
{
int m=(l+r)/;
mergesort(arrcy,l,m);
mergesort(arrcy,m+,r);
merge(arrcy,l,m,r);
}
return ;
} void merge(int arrcy[],int l,int m,int r)
{
int num1=m-l+,num2=r-m;
int i,j;
for (i=;i<num1;i++) lef[i]=arrcy[l+i];
for (i=;i<num2;i++) rig[i]=arrcy[m++i];
i=,j=;
for (int k=;k<r-l+;k++)
{
if(i>=num1||(j<num2&&lef[i]<=rig[j]))
{
arrcy[l+k]=rig[j++];
}
else
{
if(num2>j)
ans+=num2-j;
arrcy[l+k]=lef[i++];
}
}
}
方法二:树状数组或线段树
先将数组按大小进行离散化排序,从大到小,对于每个元素记录其位置,然后按数组元素大小从大到小,将其原始位置+1,后续操作时先计算1至该元素位置的和,即为与该元素的逆序对数量,进行求和即可。
分享线段树代码:
#include<bits/stdc++.h> using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <int,int> pii;
#define rep(i,x,y) for(int i=x;i<y;i++)
#define rept(i,x,y) for(int i=x;i<=y;i++)
#define pb push_back
#define fi first
#define se second
#define mp make_pair
#define dd(x) cout<<#x<<"="<<x<<" ";
#define de(x) cout<<#x<<"="<<x<<"\n";
#define mes(a,b) memset(a,b,sizeof a) const int maxn=5e5+;
pii arrcy[maxn];
class Tree
{
public:
int l,r;
ll sum;
}tree[maxn<<]; void build(int id,int l,int r);
void add(int id,int p,ll num);
ll query(int id,int l,int r); bool comp(const pii &s1,const pii &s2)
{
return s1.fi>s2.fi||(s1.fi==s2.fi&&s1.se>s2.se);
} int main()
{
int n;
scanf("%d",&n);
rept(i,,n)
{
arrcy[i].se=i;
scanf("%d",&arrcy[i].fi);
}
build(,,n);
ll ans=;
sort(arrcy+,arrcy++n,comp);
rept(i,,n)
{
ans+=query(,,arrcy[i].se);
add(,arrcy[i].se,);
}
printf("%lld\n",ans);
return ;
}
void build(int id,int l,int r)
{
tree[id].l=l;
tree[id].r=r;
tree[id].sum=;
if(l==r) return ;
int mid=(l+r)/;
build(id*,l,mid);
build(id*+,mid+,r);
}
void add(int id,int p,ll num)
{
if(tree[id].l>=p&&tree[id].r<=p)
{
tree[id].sum+=num;
return ;
}
if(tree[id].l>p||tree[id].r<p) return ;
if(tree[id*].r>=p) add(id*,p,num);
if(tree[id*+].l<=p) add(id*+,p,num);
tree[id].sum=tree[id*].sum+tree[id*+].sum;
} ll query(int id,int l,int r)
{
if(tree[id].l>=l&&tree[id].r<=r) return tree[id].sum;
if(tree[id].l>r||tree[id].r<l) return ;
ll s=;
if(tree[id*].r>=l) s+=query(id*,l,r);
if(tree[id*+].l<=r) s+=query(id*+,l,r);
return s;
}
FZU2018级算法第五次作业 m_sort(归并排序或线段树求逆序对)的更多相关文章
- FZU2018级算法第五次作业 missile(排序+枚举)
在解题报告之前,首先对同一次作业中另外一题(求逆序对)某人在未经冰少允许情况下,擅自登录冰少账号,原模原样剽窃冰少代码,并且最终还被评为优秀作业的行为表示严正抗议! 题目大意: 二维平面上给出 n 个 ...
- FZU2018级算法第三次作业 3.16 station
题目大意: 给出1-n共n个数的入栈顺序,可以随时出栈,求出栈的最大字典序. 输入示例 输出示例 51 2 3 4 5 5 4 3 2 1 54 2 5 3 1 5 3 2 4 1 题目分析: 假设目 ...
- 求逆序对常用的两种算法 ----归并排 & 树状数组
网上看了一些归并排求逆序对的文章,又看了一些树状数组的,觉得自己也写一篇试试看吧,然后本文大体也就讲个思路(没有例题),但是还是会有个程序框架的 好了下面是正文 归并排求逆序对 树状数组求逆序对 一. ...
- FZU2018级算法第一次作业 1.1fibonacci (矩阵快速幂)
题目 Winder最近在学习fibonacci 数列的相关知识.我们都知道fibonacci数列的递推公式是F(n)=F(n-1)+F(n-2)(n>=2 且n 为整数). Winder想知道的 ...
- FZU2018级算法第二次作业 2.10 逆序数(权值线段树)
题目: Nk 最近喜欢上了研究逆序数,给出一个由 1…n 组成的数列 a1,a2,a3…an, a1的逆序数就是在 a2…an 中,比 a1 小的数的数量,而 a2 的逆序数就是 a3….an 中比 ...
- 2016级算法第五次上机-F.ModricWang的水系法术
1066 ModricWang的水系法术 思路 比较典型的最大流问题,需要注意的是,题目已经暗示(明示)了这里的边是双向的,在建图的时候需要加上反向边的容量值. 解决最大流问题的基本思路就是不断在残量 ...
- 2016级算法第五次上机-E.AlvinZH的学霸养成记IV
1039 AlvinZH的学霸养成记IV 思路 难题,最大二分图匹配. 难点在于如何转化问题,n对n,一个只能攻击一个,判断是否存在一种攻击方案我方不死团灭对方.可以想到把所有随从看作点,对于可攻击的 ...
- 2016级算法第五次上机-C.Bamboo和"Coco"
1064 Bamboo和"Coco" 分析题意 每个亡灵至少一个花瓣,相邻的亡灵中思念值高的要获得的花瓣高(思念值相等是不需要花瓣一样多的).主要考贪心思路,为了使得花瓣总量最少, ...
- 2016级算法第五次上机-B.Bamboo&APTX4844魔发药水
Bamboo&APTX4844魔发药水 题意 "于是,Bamboo耐着性子,看巫师从袖子里掏出 M 瓶时光泉水和 K 粒绿色能量.每瓶时光泉水重量为 c ,生发效果为 l:每粒绿色能 ...
随机推荐
- dhcp自动分配地址
- OpenFOAM制作动画
原视频下载地址:https://yunpan.cn/cMpfh9cCjKnZI(提取码:823b)
- 根据字符串从资源中取出对应的资源ResourceManager.GetObject
ResourceManager.GetObject 根据名称从资源中取出资源 需要:我有25张 五笔图片名称是a b c d ...y 这样组成的 每张图片名字只有一个名字 我想通过字符串a取出a这张 ...
- Django连接MySQL(二)
1.首先我们需要创建好项目 2.安装MySQL数据库 3.setting中修改database设置 DATABASES = { 'default': { 'ENGINE': 'django.db.ba ...
- Ubuntu 18.04.1 安装java8
###下载tar.gz 点击选择接收协议 下载完文件之后,将文件从Windows复制到ubuntu上,可以用xShell,putty,git.这里用git 下载安装git之后,再任意位置右击,选择 g ...
- oralce 超过1亿条数据的数据库表清理实践
2018-08-18 16:58 无腿鸟 阅读(331) 评论(0) 编辑 收藏 问题:当一个表的数据量超过一亿条,要删除其中的5000w条,如何处理. 如果直接使用delete语句,会涉及到到大量的 ...
- nmcli 配置ip
配置ip: nmcli connection modify 'Wired connection 1' connection.autoconnect yes ipv4.method manual ipv ...
- 基因表达半衰期 | mRNA Half-Life
做单细胞RNA-seq分析,自然就能想到我们测到的其实是一个概率学的东西,就像女士品茶里的酵母的泊松分布一样. 真实的细胞里,一切都是连续的,从DNA到mRNA到蛋白,是有一个时间间隔的,每一个pro ...
- Spring 源码学习之环境搭建
一.下载Spring 源码 进入 https://github.com/spring-projects/spring-framework/tags 选择下载spring freamework的版本 h ...
- 多层If语句 和 表格驱动 的对比
网文提到表格驱动,总喜欢拿一层if做例子,然而这样未免也太简单. 下文是三层缩进的if和表驱动比较,大家可自行判断优劣. 业务是这样的,某景点分旺季票价和淡季票价,淡季票为旺季的一半,15岁以下孩子再 ...