题解:CF1918B(B. Minimize Inversions)
一、题意
1.题目链接
(1)原题链接
传送门。
(2)洛谷链接
传送门。
2.题意简述
给你一个整数
n
n
n,以及两个长度为
n
n
n 的序列
a
a
a 和
b
b
b。你可以做如下操作任意次:
①选择两个正整数
i
i
i、
j
j
j,保证
1
≤
i
,
j
≤
n
1≤i,j≤n
1≤i,j≤n。
②将
a
i
a_i
ai 和
a
j
a_j
aj 调换;将
b
i
b_i
bi 和
b
j
b_j
bj 调换。
你需要通过做操作使得a、b中逆序对数量之和最小。请给出操作后的序列。
二、分析
由于本题的 n n n 在 200000 200000 200000 的范围,我们需要考虑 O ( n ) O(n) O(n)、 O ( n × l o g ( n ) ) O(n×log(n)) O(n×log(n))、 O ( n × s q r t ( n ) ) O(n×sqrt(n)) O(n×sqrt(n))左右的算法。
三、知识
构造+排序+贪心。
四、解法
先只考虑
a
a
a,我们可以将它通过几次操作排序(按照升序),此时
a
a
a 中逆序对的数量为
0
0
0。把
b
b
b 和
a
a
a 绑定在一起,在修改
a
a
a 时同时修改
b
b
b,最后打印两个数组即可。
为什么它是对的呢?
考虑对于任意一对
i
i
i 和
j
j
j,在
a
a
a 中与之对应的逆序对数量为
0
0
0 或
1
1
1,在
b
b
b 中也是如此,那么总共就有
0
0
0、
1
1
1 或
2
2
2 三种可能。若
a
a
a 中原来
a
i
a_i
ai 和
a
j
a_j
aj 就有序,排序后数量不变。若本来
a
a
a 中
a
i
a_i
ai 和
a
j
a_j
aj 无序,就算时
b
b
b 中
b
i
b_i
bi 和
b
j
b_j
bj 是有序的,排序后
a
a
a 变有序
b
b
b 变无序数量仍然不变;更好的情况是
b
b
b 中也无序,那么排序后逆序对直接减少两个,岂不是更优?
五、代价
1.时间复杂度
输入 + 排序 + 输出 = O ( n ) + O ( n ∗ l o g ( n ) ) + O ( n ) = O ( n ∗ l o g ( n ) ) 输入+排序+输出=O(n)+O(n*log(n))+O(n)=O(n*log(n)) 输入+排序+输出=O(n)+O(n∗log(n))+O(n)=O(n∗log(n))
2.空间复杂度
O ( n ) O(n) O(n)
六、代码
#include<bits/stdc++.h>
#define N 220000
using namespace std;
struct Number{
int a,b;
bool operator<(Number ot)const{
return a<ot.a;
}
};
Number num[N]={};
int n=0,t=0;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&num[i].a);
}
for(int i=1;i<=n;i++){
scanf("%d",&num[i].b);
}
sort(num+1,num+1+n);
for(int i=1;i<=n;i++){
printf("%d ",num[i].a);
}
printf("\n");
for(int i=1;i<=n;i++){
printf("%d ",num[i].b);
}
printf("\n");
}
return 0;
}