博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【NOIP】提高组2013 火柴排队
阅读量:6485 次
发布时间:2019-06-23

本文共 1479 字,大约阅读时间需要 4 分钟。

【题意】两列n个火柴,分别有高度ai和bi(同一列高度互不相同),每次可以交换一列中的两个相邻火柴,定义距离为∑(ai-bi)^2,求使距离最小的最少交换次数,n<=10^5。

【算法】逆序对

【题解】∑(ai-bi)^2=∑ai^2+∑bi^2-∑ai*bi,其中∑ai^2和∑bi^2为常数,则要使∑ai*bi最大。

对于两个序列的∑ai*bi,根据排序不等式,有逆序和<=乱序和<=正序和。(可以理解为两数离得越近,乘积越大)

将两序列各自离散化后,问题转化为使两序列每位数字相等

为了方便统计,换种角度说就是A数组的每个数字需要移动到一个对应的位置,所以我们设置C数组表示A数组中每个数应该去的位置

(具体操作中最方便的方法是:A和B排序,然后C[A[i].id]=B[i].id

那么实际上我们就是要通过交换使C数组升序排列,问题转化为通过最少次交换相邻数字使一个序列升序排列

要使交换次数最少,就使每次交换消除一个逆序对。如果不存在相邻逆序对,可以证明序列已经升序排列。

所以答案是逆序对数,可以使用树状数组或归并排序求逆序对,复杂度O(n log n)。

#include
#include
#include
#include
#define lowbit(x) x&-x#define ll long longusing namespace std;const int maxn=100010,MOD=99999997;//ji de qu moint read(){ char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t;}int n,c[maxn],A[maxn];struct cyc{
int num,id;}a[maxn],b[maxn];bool cmp1(cyc a,cyc b){
return a.num
=1;i-=lowbit(i))ans+=c[i];return ans;}int main(){ n=read(); for(int i=1;i<=n;i++)a[i].num=read(),a[i].id=i; for(int i=1;i<=n;i++)b[i].num=read(),b[i].id=i; sort(a+1,a+n+1,cmp1);sort(b+1,b+n+1,cmp1); for(int i=1;i<=n;i++)A[a[i].id]=b[i].id; ll ans=0; for(int i=1;i<=n;i++){ insert(A[i]); ans+=i-query(A[i]);// } printf("%lld",ans%MOD); return 0;}
View Code

记得取模!

转载于:https://www.cnblogs.com/onioncyc/p/7779102.html

你可能感兴趣的文章
H3C品牌刀片系统强势首发
查看>>
【CSS系列】图像映射
查看>>
First blood
查看>>
java 冒泡排序和快速排序 实现
查看>>
SQL存储过程中的几个常见设定SET QUOTED_IDENTIFIER/NOCOUNT/XACT_ABORT ON/OFF
查看>>
Silverlight与Flash区别之一
查看>>
删除恢复Hadoop集群中的DataNode
查看>>
Silverlight 2动态创建矩形对象(附完整源代码)
查看>>
从京东技术演进看互联网企业的成长历程
查看>>
MFC ado+mysql+odbc技术分享
查看>>
js中让字符串中特定字符红色显示
查看>>
HttpClient4.5教程-第二章-连接管理
查看>>
redhat Nginx 安装
查看>>
oracle 配置监听
查看>>
moosefs即将发布新版
查看>>
SmartGit 试用过期
查看>>
python 测试驱动开发的简单例子
查看>>
Aes 加密简单例子
查看>>
AE 线编辑
查看>>
软件设计之UML—UML的构成[上]
查看>>