P1966 火柴排队
显然有一个想法,把 $A,B$ 从小到大一一对应,这样距离最小,证明的话好像挺显然的
设 $A_i<A_{i+1}$ ,$B_{i}<B_{i+1}$,那么如果 $A_i$ 对应 $B_i$,$A_{i+1}$ 对应 $B_{i+1}$
距离为 $(A_i-B_i)^2+(A_{i+1}-B_{i+1})^2=A_{i}^{2}-2A_iB_i+B_{i}^2+A_{i+1}^{2}-2A_{i+1}B_{i+1}+B_{i+1}^2$
如果 $A_i$ 对应 $B_{i+1}$ ,$A_{i+1}$ 对应 $B_{i}$ 那么距离同样可以算出,为
$A_{i}^2-2A_{i}B_{i+1}+B_{i+1}^2+A_{i+1}^2-2A_{i+1}B{i}+B_{i+1}^2$
两式相减,得到 $-2(A_iB_i+A_{i+1}B_{i+1}-A_{i+1}B_{i}-A_{i}B_{i+1})\ =\ -2(A_i(B_i-B_{i+1})+A_{i+1}(B_{i+1}-B_i))\ =\ -2((A_i-A_{i+1})(B_i-B_{i+1}))$
因为 $A_i<A_{i+1}$ ,$B_{i}<B_{i+1}$,所以上式小于 $0$
所以按从小到大一一对应是最优的
然后考虑交换次数怎么求,显然 $B$ 的某个交换 $A$ 都有对应的交换,两者等价
所以只要考虑 $A$ 怎么交换就行。每个火柴高度各不相同,确定了 $A$ 和 $B$ 的唯一的对应关系,所以我们知道每个 $A_{i}$ 最终的位置
设初始位置为 $i$ 的火柴最终要到达位置 $C_i$,那么我们可以发现 $C_i$ 是一个 $1$ 到 $n$ 的排列
而且最终交换完成后,$C_i$ 会变成 $1,2,3,...,n$ 的样子
考虑用最少的步数把 $C_i$ 排序,显然这个就是答案,可以证明最小步数等于初始时 $C_i$ 的逆序对数量
证明如下:
考虑一次交换,它要么减少 $0$ 逆序对,要么减少 $1$ 逆序对,而最终状态的逆序对数量为 $0$(也是唯一逆序对为 $0$ 的状态)
考虑冒泡排序的过程,每次选择 $i<j$ 且 $C_i>C_j$ 的数对进行交换,这样最终一定可以达到最终状态
而且发现冒泡排序时,每次交换都会减少 $1$ 逆序对,所以我们交换时就可以模拟冒泡排序,达到最终状态
因为每次交换逆序对最多减少 $1$,所以逆序对数量就是最少交换次数
我们可以用树状数组求逆序对数量
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e6+7,mo=99999997; int n,c[N]; struct dat{ int v,id; inline bool operator < (const dat &tmp) const { return v<tmp.v; } }a[N],b[N]; int t[N]; ll ans; inline void add(int x) { while(x<=n) t[x]++,x+=x&-x; } inline int ask(int x) { int res=0; while(x) res+=t[x],x-=x&-x; return res; } int main() { n=read(); for(int i=1;i<=n;i++) a[i].v=read(),a[i].id=i; for(int i=1;i<=n;i++) b[i].v=read(),b[i].id=i; sort(a+1,a+n+1); sort(b+1,b+n+1); for(int i=1;i<=n;i++) c[a[i].id]=b[i].id; for(int i=n;i;i--) ans+=ask(c[i]),add(c[i]); printf("%lld\n",ans%mo); return 0; }
原文地址:https://www.cnblogs.com/LLTYYC/p/11367764.html
- 云计算如何在银行业务发挥作用?
- SNH48 要推出定制 AI 形象,和初音未来有什么不同?
- 字节对齐
- 微信更新为小程序引入游戏功能,朋友圈又刷屏了
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序)
- Linux同步机制(二) - 条件变量,信号量,文件锁,栅栏
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)
- zookeeper集群搭建
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[编程篇]
- 浅谈反馈式按钮的设计与实现
- 对比手游和PC游戏的发展,小程序会成为手游开发的热点?
- 雷军旗下金山云再获融资2.2亿美元
- WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[WS标准篇]
- zookeeper配置详解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 3分钟短文 | PHP多维数组搜索值,就只能for循环?这样写更高效
- 如何获得tomcat管理员账号
- ant target间的dependency
- 如何用ant将JSP项目打成war包
- 3分钟短文 | MySQL备份和迁移sql文件,这个指令基础又关键
- 如何用ant给Java项目生成文档
- ant build里如何指定classpath
- Tomcat服务器java.lang.IllegalArgumentException异常
- 动态控制SAP CRM附件的可编辑性
- 关于node.js:ExpressJS、Websocket中的session会话共享
- 【STM32F429开发板用户手册】第23章 STM32F429的USART串口基础知识和HAL库API
- 【STM32F407开发板用户手册】第23章 STM32F407的USART串口基础知识和HAL库API
- 小姐姐提灯给你讲讲动态规划(万字长文)
- 解决fedora启动时显示cannot open font file true的办法 By HKL,
- 盘点 6 个被淘汰的 Java 技术,它们都曾经风光过!