IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【做题笔记】P1966 [NOIP2013 提高组] 火柴排队 -> 正文阅读

[数据结构与算法]【做题笔记】P1966 [NOIP2013 提高组] 火柴排队

题目:https://www.luogu.com.cn/problem/P1966


首先分析题目定义的距离式子:
∑ i = 1 n ( a i ? b i ) 2 \sum_{i = 1}^{n}(a_i-b_i)^2 i=1n?(ai??bi?)2
是不是没有头绪?

再化简一下:
∑ i = 1 n a i 2 ? 2 a b + b i 2 \sum_{i = 1}^{n}{a_i}^2-2ab+{b_i}^2 i=1n?ai?2?2ab+bi?2
= ∑ i = 1 n a i 2 + b i 2 ? ∑ i = 1 n 2 a b =\sum_{i = 1}^{n}{a_i}^2+{b_i}^2 - \sum_{i = 1}^n2ab =i=1n?ai?2+bi?2?i=1n?2ab

很显然 ∑ i = 1 n a i 2 + b i 2 \sum_{i = 1}^{n}{a_i}^2+{b_i}^2 i=1n?ai?2+bi?2 是不会变的,于是要使 ∑ i = 1 n ( a i ? b i ) 2 \sum_{i = 1}^{n}(a_i-b_i)^2 i=1n?(ai??bi?)2 最小,让 ∑ i = 1 n 2 a b \sum_{i = 1}^n2ab i=1n?2ab 最大即可。

易证很容易猜到当两个序列按升序或降序排列后,可以使 ∑ i = 1 n 2 a b \sum_{i = 1}^n2ab i=1n?2ab 取最小值,这种想法是正确的(我太菜,不会严格证明)。

所以这道题就转换成:给定两个数列,要使两个数列中大小排名相等的元素一一对应(数列 a a a 第一大的数对应数列 b b b 第一大的数,数列 a a a 第二大的数对应数列 b b b 第二大的数,以此类推),求最小的交换次数。

首先定义一个结构体, n u m num num 表示数组元素的值, i d id id 表示数组元素在原来序列中的位置。读入的时候记录一下 i d id id,再将 a a a b b b 两数组升序排序。

那么该怎么求最小交换次数呢?

先来把玩一下样例二:

? 原数组 ?? 排序后?
? a n u m a_{num} anum??? 1 3 4 2?? 1 2 3 4 ?
? a i d a_{id} aid? ?? 1 2 3 4 ?? 1 4 2 3?
? b n u m b_{num} bnum??? 1 7 4 2?? 1 2 4 7?
? b i d b_{id} bid? ?? 1 2 3 4 ?? 1 4 3 2 ?

定义一个数组 c c c,有 c [ a [ i ] . i d ] = b [ i ] . i d c[a[i]_ {.id}]=b[i]_ {.id} c[a[i].id?]=b[i].id?

由上表可知:

c [ a [ 1 ] . i d ] = b [ 1 ] . i d , c [ 1 ] = 1 c[a[1]_ {.id}]=b[1]_ {.id} , c[1]=1 c[a[1].id?]=b[1].id?,c[1]=1

c [ a [ 2 ] . i d ] = b [ 2 ] . i d , c [ 4 ] = 4 c[a[2]_ {.id}]=b[2]_ {.id} , c[4]=4 c[a[2].id?]=b[2].id?,c[4]=4

c [ a [ 3 ] . i d ] = b [ 3 ] . i d , c [ 2 ] = 3 c[a[3]_ {.id}]=b[3]_ {.id} , c[2]=3 c[a[3].id?]=b[3].id?,c[2]=3

c [ a [ 4 ] . i d ] = b [ 4 ] . i d , c [ 3 ] = 2 c[a[4]_ {.id}]=b[4]_ {.id} , c[3]=2 c[a[4].id?]=b[4].id?,c[3]=2

所以 c c c 数组就是 [ 1 , 3 , 2 , 4 ] [1,3,2,4] [1,3,2,4](其实就是个双关键字排序)。

我们知道当 a [ i ] . i d = b [ i ] . i d a[i]_ {.id}=b[i]_ {.id} a[i].id?=b[i].id? 时, c i = i c_i=i ci?=i

所以 ? i , c i = i ?i,c_i=i ?i,ci?=i 时, a a a b b b 数组排序前的值的排名一一对应。

于是原问题就进一步转换成了:给定序列 c c c,每次可翻转其中两个数,求最小的翻转次数,使得序列 c c c 升序排序。

这不就是求逆序对吗?

用归并排序就能轻松解决。


AC code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
template<class T>inline void read(T &s){
    int f=1; s=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
    s*=f;
}
const int MAXN=1e5+10;
const int md=1e8-3;
ll c[MAXN],q[MAXN],ans;
int n;
struct node{
	int num,id;
	inline void rd(int i){read(num),id=i;};
}a[MAXN],b[MAXN];
void merge_sort(int l,int r){
	if(l==r) return;
	int mid=(l+r)>>1;
	merge_sort(l,mid),merge_sort(mid+1,r);
	int head1=l,head2=mid+1;
	for(int i=l;i<=r;i++){
		if(head2<=r&&(head1>=mid+1||c[head1]>c[head2]))
			q[i]=c[head2++];
		else q[i]=c[head1++],ans+=(head2-mid-1)%md; 
	} 
	for(int i=l;i<=r;i++) c[i]=q[i];
}
inline bool cmp(const node&x,const node&y){
	return x.num<y.num;
}
signed main(){
	ios::sync_with_stdio(false);
	read(n);
	for(int i=1;i<=n;i++) a[i].rd(i);
	for(int i=1;i<=n;i++) b[i].rd(i);
	sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++)
		c[a[i].id]=b[i].id;
	merge_sort(1,n);
	cout<<ans%md;
	return 0;
} 

完结撒花~

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-29 23:20:21  更:2022-01-29 23:22:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:35:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码