B.
思路:要求找到两队的相等,则至少要有两个数出现两次,则分别让a为1和2 .1和3.
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n;
cin>>n;
vector<int> a(n);
for (int i=0;i<n;i++){
cin>>a[i];
}
vector<int> b(n,1);
vector<vector<int>> in(101);
for (int i=0;i<n;i++){
in[a[i]].push_back(i);
}
int k=2;
for (int i=1;i<=100;i++){
if(in[i].size()>=2){
b[in[i][0]]=k;
k++;
}
if(k>3){
break;
}
}
if(k<=3){
cout<<-1<<endl;
}
else {
for (int i=0;i<n;i++){
cout<<b[i]<<" ";
}
cout<<'\n';
}
}
signed main()
{
int t;
cin>>t;
while(t--){
solve();
}
}
C.
思路:通过分析可以发现在每次选择x 点移动后,x 点永远会位于last 处。
1.如果最后一个数小于等于n ,则进入循环。
2.k=min(k,n) 如果撤销了N 次 无变化的话,则会进入循环。
3.每次撤销都推导出上一个last 处的数 last= (last-a[last]+n)%n;
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n,k;
cin>>n>>k;
vector<int> a(n);
for (int i=0;i<n;i++){
cin>>a[i];
}
int last=n-1;
for (int i=0;i<min(k,n);i++){
if(a[last]>n){
cout<<"No"<<endl;
return ;
}
last=(last-a[last]+n)%n;
}
cout<<"Yes"<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}
D.
思路:LIS(c)>=LIS(a) 因为a 是 c 的子序列。而LIS(C)<=LIS(a+1) ,因为我们可使b以降序放入,所以最多会加一。
但我们可以证明LIS(c) 会等于LIS(a) . 每次都将b放在其大于的a前面,类似于merge函数的过程,
按照从大到小合并数组。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n,m;
cin>>n>>m;
vector<int> a(n),b(m),c(n+m);
for (int i=0;i<n;i++) cin>>a[i];
for (int i=0;i<m;i++) cin>>b[i];
sort(b.rbegin(),b.rend());
merge(a.begin(),a.end(),b.begin(),b.end(),c.begin(),greater<int>());
for (int i=0;i<n+m;i++){
cout<<c[i]<<" ";
}
cout<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
}