专栏文章
题解:CF2060G Bugged Sort
CF2060G题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mipv2i2i
- 此快照首次捕获于
- 2025/12/03 18:25 3 个月前
- 此快照最后确认于
- 2025/12/03 18:25 3 个月前
有意思的简单题。
判定能否通过某种操作达到确定状态的题目,我们可以尝试进一步简化操作。显然每一列是 或 ,不妨将列内序与列间序分开考虑。
由于我们可以同时改变列内序和列间序,所以我们考虑如何只改变列间序(列内序)。事实上,对于两列 ,只需要引入第三列 ,依次交换 即可只改变列间序。
但是由于每次改变两列的列间序,所以一定只能列间序改变偶数列。
于是问题变成了若干对 ,任意排序,可以进行偶数次内部交换,要求分别 递增。考虑贪心,先不考虑内部交换偶数次的限制,对于每一对都使 ,直接看成线段排序,依次枚举即可。如对于线段 ,若 ,则第二条线段一定是 ,其中 ,否则无解,以此类推。
考虑内部序,注意到对于线段有交的连通块,第一条线段的内部序定后,后面的实际上都已经确定,所以每次只能同时翻转一个连通块。假设我们已经排序,对于总次数的奇偶性,偶长块不改变,奇长块一定改变,所以要么初始为偶数,要么存在奇长块。
代码比
CPPdp 好写一些。#include<bits/stdc++.h>
#define maxn 210005
#define fi first
#define se second
using namespace std;
const int inf=1e9;
int n,id[maxn];
pair<int,int>p[maxn];
inline void solve(){
int sum=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&p[i].fi);
for(int i=1;i<=n;i++) scanf("%d",&p[i].se),id[i]=i;
for(int i=1;i<=n;i++) if(p[i].fi>p[i].se) swap(p[i].fi,p[i].se),sum^=1;
sort(id+1,id+n+1,[](int x,int y){return p[x]<p[y];});
int r=0,cnt=0,fl=0;
p[id[n+1]=n+1].fi=inf;
for(int it=1,i=id[it];it<=n+1;it++,i=id[it]){
if(p[i].fi<=r){
if(p[i].se<r) return puts("NO"),void();
r=p[i].se;
cnt^=1;
continue;
}
if(it!=1) fl|=cnt;
cnt=1,r=p[i].se;
}
puts(sum&&!fl?"NO":"YES");
}
signed main(){
signed T=1;
scanf("%d",&T);
while(T--) solve();
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...