Let ships that ran aground re-launch their sails
差点做出来了,感谢 Deepseek,让我认为自己假了。
怎么我的思路更近似于 AI 的做法。
对着 \(A\) 建图感觉没有说法,因此对着 \(B\) 建图,建出来的必然是 \(DAG\)。
链的做法是显然的,考虑菊花。菊花要求我们拥有往回跳的能力(不然无解了)。
而 \(DAG\) 的本质近似于链加菊花,因此我们考虑套上去,发现链的瓶颈在于我们需要利用 \(a\) 实现链之间的跳跃。考虑怎么进行跳跃。
贪心的,我们希望下标尽可能的小,否则的话,也就是说我们会出现下标大反而更优秀的情况,考虑什么时候会出现,就是前面某个位置的结束点很小的时候。但是考虑这种情况如果真的出现了,我们不管怎么选,都没有机会再挽回了,因此我们尽可能的让下标小就是对的了。
当然有点伪证的成分了,感性理解是好理解的。反正官方没有证明。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 1e3 + 10;
int a[N],b[N];
int n;
void solve(){
cin >> n;
for(int i=1;i<=n;i++)
cin >> a[i];
for(int i=1;i<=n;i++)
cin >> b[i];
int cnt = 0,st = -1;
for(int i=1;i<=n;i++){
if(a[i] > b[i]){
cout << -1 << "\n";
return ;
}
if(a[i] < b[i]){
cnt ++ ;
if(cnt == 1) st = i;
}
}
if(cnt == 0){
cout << "0 1\n";
return ;
}
int pos = st;
vector<int> res;res.clear();
while(cnt){
if(a[pos] < b[pos]){
while(a[pos] < b[pos] && (a[pos] >= pos || a[a[pos]] == b[a[pos]])){
a[pos] ++ ;
res.push_back(1);
}
if(a[pos] == b[pos])
cnt -- ;
}
if(cnt == 0 || a[pos] == pos) break;
pos = a[pos];
res.push_back(2);
}
if(cnt){
cout << -1 << "\n";
return ;
}
cout << res.size() << " " << st << "\n";
for(int op : res)
cout << op << " ";
cout << "\n";
}
int main(){
IOS;
int T;
cin >> T;
while(T -- )
solve();
return 0;
}

浙公网安备 33010602011771号