题解:CF2023A Concatenation of Arrays
zengxuheng
·
·
题解
分析
可以看出,我们有几种排序方式。
第一种:比较两个数组之间相互逆序对大小。
例如:
数组 a1 与 a2 有 cnt1 个逆序对。
数组 a2 与 a1 有 cnt2 个逆序对。
比较 cnt1 与 cnt2 大小来排序。
第二种:看哪个数组有两个数组最大值,那个数组就排在后面。
例如:
数组 a1 元素为 [2,3],数组 a2 元素为 [1,5]。
因为数组 a2 中有两个数组最大值:5,因此将 a2 排在 a1 后面。
第三种:按和排序。
例如:
数组 a1 元素为 [2,3],和为 5;数组 a2 元素为 [1,5],和为 6。
因为 6 > 5,因此将 a2 排在 a1 后面。
证明对错:
第一种:
由于比较两个数组之间相互逆序对大小并不能推向全局,贪心思想必须有传递性,于是废除。
例子:
由于 $a1$ 与 $a2$ 逆序对数量都为 $2$,我们将 $a2$ 排在 $a1$ 后面,$a2$ 与 $a3$ 逆序对数量都为 $2$,我们将 $a3$ 排在 $a2$ 后面。
于是就有了以下一个序列:
$$
(3,3,1,5,2,2)
$$
明显不是最优。
---
第二、三种都具有传递性,所以都可以作为答案。
# Code
```cpp
#include<bits/stdc++.h>
using namespace std;
pair<int,int> a[100010];
inline int read() {
int x=0,f=1;
char ch=getchar/*_unlocked*/();
while (ch<48||ch>57) {
if (ch=='-') f=-1;
ch=getchar/*_unlocked*/();
}
while (ch>=48&&ch<=57) {
x=x*10+ch-48;
ch=getchar/*_unlocked*/();
}
return x*f;
}
template<typename T>
inline void write(T x,int f=1) {
if(x<0) putchar/*_unlocked*/('-'),x=-x;
if(x>9) write(x/10,0);
putchar/*_unlocked*/(x%10+'0');
if(f==1)putchar/*_unlocked*/('\n');
if(f==2) putchar/*_unlocked*/(' ');
return;
}
bool cmp(pair<int,int> x,pair<int,int> y) {
int a=x.first,a1=x.second,b=y.first,b1=y.second;
int maxn=max({a,a1,b,b1});
if((a==maxn||a1==maxn)&&(b==maxn||b1==maxn)) return (a+a1)<(b+b1);
else if(a==maxn||a1==maxn) return 0;
else if(b==maxn||b1==maxn) return 1;
}
int main() {
int t=read();
while(t--) {
int n=read();
int cnt=0;
for(register int i = 1; i <= n; i++) a[i]= {read(),read()};
sort(a+1,a+n+1,cmp);
for(register int i = 1; i <= n; i++) cout<<a[i].first<<' '<<a[i].second<<' ';
cout<<'\n';
}
return 0;
}
```