题解:CF2023A Concatenation of Arrays

· · 题解

分析

可以看出,我们有几种排序方式。

第一种:比较两个数组之间相互逆序对大小。

例如:

数组 a1a2cnt1 个逆序对。

数组 a2a1cnt2 个逆序对。

比较 cnt1cnt2 大小来排序。

第二种:看哪个数组有两个数组最大值,那个数组就排在后面。

例如:

数组 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; } ```