当前位置:网站首页>Luogu P1966: [NOIP2013 提高组] 火柴排队 [树状数组+逆序对]
Luogu P1966: [NOIP2013 提高组] 火柴排队 [树状数组+逆序对]
2022-08-05 08:11:00 【9ack!?】
[NOIP2013 提高组] 火柴排队
题目描述
涵涵有两盒火柴,每盒装有 n n n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑ ( a i − b i ) 2 \sum(a_i-b_i)^2 ∑(ai−bi)2
其中 a i a_i ai 表示第一列火柴中第 i i i 个火柴的高度, b i b_i bi 表示第二列火柴中第 i i i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 1 0 8 − 3 10^8-3 108−3 取模的结果。
输入格式
共三行,第一行包含一个整数 n n n,表示每盒中火柴的数目。
第二行有 n n n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n n n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式
一个整数,表示最少交换次数对 1 0 8 − 3 10^8-3 108−3 取模的结果。
样例 #1
样例输入 #1
4
2 3 1 4
3 2 1 4
样例输出 #1
1
样例 #2
样例输入 #2
4
1 3 4 2
1 7 2 4
样例输出 #2
2
提示
【输入输出样例说明一】
最小距离是 0 0 0,最少需要交换 1 1 1 次,比如:交换第 1 1 1 列的前 2 2 2 根火柴或者交换第 2 2 2 列的前 2 2 2 根火柴。
【输入输出样例说明二】
最小距离是 10 10 10,最少需要交换 2 2 2 次,比如:交换第 1 1 1 列的中间 2 2 2 根火柴的位置,再交换第 2 2 2 列中后 2 2 2 根火柴的位置。
【数据范围】
对于 10 % 10\% 10% 的数据, 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10;
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100;
对于 60 % 60\% 60% 的数据, 1 ≤ n ≤ 1 0 3 1 \leq n \leq 10^3 1≤n≤103;
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105, 0 ≤ 0 \leq 0≤ 火柴高度 < 2 31 < 2^{31} <231。
思路
可以猜想出当两个数组中第 i i i大的数字均相对应的时候,两个数组的距离最短。这个随便造两个例子就能大概证明结论是正确的。
然后我们就先使用离散化对数组进行处理,具体离散化的过程可以参考我这篇博客。
接下来的操作就非常精妙了,我们现在要解决的问题是,对于两个离散化后的数组 d 1 d_1 d1和 d 2 d_2 d2,其中一个数组通过几次相邻元素的交换之后可以得到另一个数组。下面我们通过新建一个数组 q q q,令 q [ d 1 [ i ] ] = d 2 [ i ] q[d_1[i]]=d_2[i] q[d1[i]]=d2[i],得到的 q q q数组就是以 d 1 d_1 d1为关键字,把 d 2 d_2 d2中的每个元素映射到 q q q中。
那么我们的问题就转化成了求解 q q q数组中逆序对的个数,这个和我上一篇博客解决的问题就几乎一样了。
代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
const int mod = 1e8-3;
int a1[maxn], d1[maxn], a2[maxn], d2[maxn];
int c[maxn], q[maxn];
int n;
bool cmp1(int x, int y) {
return a1[x]>a1[y];
}
bool cmp2(int x, int y) {
return a2[x]>a2[y];
}
int lowbit(int x) {
return x&(-x);
}
void add(int i) {
while(i <= n) {
c[i] = (c[i]+1)%mod;
i += lowbit(i);
}
}
int getsum(int i) {
int res = 0;
while(i > 0) {
res = (res+c[i])%mod;
i -= lowbit(i);
}
return res;
}
int main(void)
{
freopen("in.txt", "r", stdin);
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a1[i]);
d1[i] = i;
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &a2[i]);
d2[i] = i;
}
sort(d1+1, d1+n+1, cmp1);
sort(d2+1, d2+n+1, cmp2);
for(int i = 1; i <= n; ++i) {
q[d1[i]] = d2[i];
}
int ans = 0;
for(int i = n; i >= 1; --i) {
add(q[i]);
ans = (ans+getsum(q[i]-1))%mod;
}
printf("%d\n", ans%mod);
/* for(int i = n; i >= 1; ++i) { */
/* printf("%d ", q[i]); */
/* } */
return 0;
}
边栏推荐
猜你喜欢

D2--FPGA SPI接口通信2022-08-03

网络安全研究发现,P2E项目遭遇黑客攻击只是时间问题

DataFrame insert row and column at specified position

【结构体内功修炼】结构体实现位段(二)

The Coolest Kubernetes Network Solution Cilium Getting Started Tutorial

图扑软件与华为云共同构建新型智慧工厂

复现一次循环和两次循环

宝塔实测-搭建中小型民宿酒店管理源码

MySQL database error The server quit without updating PID file (/var/lib/mysql/localhost.localdomain.pid)

Data source object management Druid and c3p0
随机推荐
行业应用软件项目经理三步曲
Spark cluster deployment (third bullet)
Antdesign a-select 下拉框超出长度换行显示
egg框架中解决跨域的三种方案
openSource 知:社区贡献
v-if/v-else determines whether to display according to the calculation
Moonbeam团队发布针对整数截断漏洞的紧急安全修复
力扣刷题八月第一天
基于多块信息提取和马氏距离的k近邻故障监测
C语言制作-QQ聊天室
8.4模拟赛总结
v-if/v-else根据计算判断是否显示
复现一次循环和两次循环
Controller-----controller
浅谈自动采集程序及入库
DataFrame insert row and column at specified position
SVG big fish eat small fish animation js special effects
The color of life divine
Detailed explanation of DNS query principle
[Structural Internal Power Cultivation] Structural Realization Stages (2)