CF1481C Fence Painting

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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值