emmm做完AB就一个小时了,前面代码量也不算特别小,对我这种菜鸡,我就知道C我肯定是冲不出来了,写了写试试,结束以后15分钟把样例过了,结果今下午又改了一下午,细节多,然后我又想的很麻烦,开了特别多特别多的数组。就算是。。找个地方存我的垃圾代码。
思路是这样的:
因为最后要求的是每个painter的安排,那么就先求出每一个需要改的地方所要对应的painter,然后再把剩下的慢慢放上,如果放不上,说明不成立。
准备工作:
记录所有要换的地方(颜色+位置)
记录每个painter可以修改的颜色和他所在的位置。
记录修改后所有的颜色
记录每个颜色的一个位置(后期有painter的颜色多余,就把他换掉)
然后开始求解每一个painter要修改的地方:(所有的答案记在ans数组)
第一次 先确定必须要修改的地方,记下ans[j] = i
第二次 遍历ans[i]= 0的点 ,找到那些在painter可以在最终颜色里面找的位置,将这个点的ans赋值为标记的颜色的位置
第三次 遍历ans[i]= 0的点,此时还不能找到的位置,都是颜色不能在最终修改后找到的颜色,我们向后找一个不是0的位置,将这个ans的值记为位置。(最终这个点会变成后面那个painter赋给他的颜色)。
在这个过程中,如果有地方不能够实现,那么就是不成立的情况。
#include<bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 100005;
int a[N],b[N],c[N];
int num[N],val[N],ans[N],pos[N];
struct node{
int v,r;
};
vector<int>g[N];
node sum[N];
int main(){
int t,n,m;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
int p = 0;
memset(num,0,sizeof(num));
memset(val,0,sizeof(val));
memset(ans,0,sizeof(ans));
memset(pos,0,sizeof(pos));
for(int i = 1;i<=n;i++){
vector<int>().swap(g[i]);
}
for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
for(int i = 1;i<=n;i++){
scanf("%d",&b[i]);
if(b[i]!=a[i]) {
sum[++p].v = b[i]; //不匹配的部分,b[i]为最终结果
sum[p].r = i;
}
num[b[i]] ++; //所有要变的颜色
pos[b[i]] = i;
}
bool f = true;
for(int i = 1;i<=m;i++){
scanf("%d",&c[i]); //拥有的可以变化的部分
val[c[i]] ++;
g[c[i]].push_back(i);//添加他的序号
}
if(p>m) f = false;
for(int i = 1;i<=p&&f==true;i++){
int x = sum[i].v ;
if(val[x]>0) {
val[x] --;
int l = g[x].size() -1;
ans[g[x][l]] = sum[i].r ;
g[x].pop_back() ;
}
else {
f = false;
}
}
/*
}*/
for(int i = 1;i<=m&&f==true;i++){
if(ans[i]==0&&num[c[i]]>0){
ans[i] = pos[c[i]];
}
}
for(int i = 1;i<=m&&f==true;i++){
if(ans[i]==0){
int p = i+1;
while(p<=m){
if(ans[p]!=0) {
ans[i] = ans[p];
break;
}
else{
p++;
}
}
if(p==m+1){
f = false;
}
}
}
if(f == false){
printf("NO\n");
continue;
}
else{
printf("YES\n");
}
for(int i = 1;i<=m;i++){
printf("%d ",ans[i]);
}
printf("\n");
}
return 0;
}