考虑构造。
首先第一轮构造我们把第一次出现的数放到 \(p\) 里面,第二次出现的放到 \(q\) 里面。如果有数第三次出现呢?那么显然无解。
那么现在 \(p\) 和 \(q\) 中都填了一些数,但是因为题目要求,所以填后面某个位置的数时要比这个位置已经填的数小所以把排列中没有的数存起来,按照从小到大的顺序填入即可,填的时候优先填入另一个排列对应位置较小的位置即可。显然,这是一种贪心的构造。
那么注意好代码实现就好,不要像我调了半个小时
#include<bits/stdc++.h>
//#define int long long
//#define lowbit(x) (x&-(x))
using namespace std;
const int maxn = 2e5+10;
int t;
int a[maxn],cnt[maxn];
int p[maxn],q[maxn];
int Search[maxn][2];
void work(){
int n;
int flag=0;
stack<int> op;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
Search[i][0]=Search[i][1]=p[i]=q[i]=cnt[i]=0;
}
for(int i=1;i<=n;i++){
if(cnt[a[i]]==2){
cout<<"NO\n";
return ;
}
if(cnt[a[i]]==0){
p[i]=a[i];
Search[a[i]][0]=i;
}
else{
flag=1;
q[i]=a[i];
Search[a[i]][1]=i;
}
cnt[a[i]]++;
}
if(flag==0){
cout<<"YES\n";
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<'\n';
for(int i=1;i<=n;i++){
cout<<a[i]<<' ';
}
cout<<'\n';
return ;
}
for(int i=1;i<=n;i++) cnt[i]=0;
for(int i=1;i<=n;i++){
cnt[p[i]]++;
}
for(int i=n;i>=1;i--){
if(cnt[i]==0){
op.push(i);
}
}
for(int i=1;i<=n;i++){
if(p[Search[i][1]]==0){
p[Search[i][1]]=op.top();
op.pop();
}
}
for(int i=1;i<=n;i++){
cnt[i]=0;
}
for(int i=1;i<=n;i++){
cnt[q[i]]++;
}
for(int i=1;i<=n;i++){
if(cnt[i]==0)
op.push(i);
}
for(int i=1;i<=n;i++){
if(q[Search[i][0]]==0){
q[Search[i][0]]=op.top();
op.pop();
}
}
for(int i=1;i<=n;i++){
if(max(p[i],q[i])!=a[i]){
cout<<"NO\n";
return ;
}
}
cout<<"YES\n";
for(int i=1;i<=n;i++){
cout<<p[i]<<' ';
}
cout<<'\n';
for(int i=1;i<=n;i++){
cout<<q[i]<<' ';
}
cout<<'\n';
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
work();
}
return 0;
}
标签:Search,int,题解,CF1768C,cnt,maxn
From: https://www.cnblogs.com/chifan-duck/p/17061079.html