C. Fence Painting(ranting 1600)超详细题解
前言
本系列的意义在于两点,一则是作为本人(一个编程初学者)的学习笔记记录,二则希望能对后来者提供一些帮助,因为本人也为新手,难免有些错误或讲述不清之处,恳请大家指出或提出建议,本人也会虚心修改。
本系列的目标是帮助大家解决一些codeforces上,ranting1600+(或者之后会改为1300+,看博主水平吧)的题目
一、题目及翻译
1. 原题(贴图)
2. 翻译
- 机翻版
- 省流版
给定的n和数列a和数列b,再给定m个元素(每个元素只能用一次),让我们用且必须用m次操作,将a通过给定元素替换成b
二、解析及AC代码
1.解析
我们先讨论一下无解的情况:
- 如果给的颜色全是b中不存在的。为什么呢 ? 如果给的颜色全是b中不存在的,那么无论,怎么涂,都必定会使a与b至少有一个元素不同
- 如果在 a i a_i ai ≠ \neq = b i b_i bi时,c中不存在 b i b_i bi。为什么呢? 如果在 a i a_i ai ≠ \neq = b i b_i bi时,c中不存在 b i b_i bi,那么无论,怎么涂,都必定会使 a i a_i ai与 b i b_i bi不同
如果题目不是以上两种情况则有解,那么怎么构造出解呢?从贪心的角度思考,当存在 a i a_i ai ≠ \neq = b i b_i bi时,我们刷上 b i b_i bi,否则我们将c中所有元素刷到最后一个 a i a_i ai= b i b_i bi= c j c_j cj的地方去(可以理解为找到最后刷的地方,然后将其他元素当做不存在元素对待),而对于不存在的元素,我们把它刷到最后一个刷的地方去
那么,此时同学们就可以自己去尝试一下了,如果还是不太理解,可以参考下博主下面的AC代码
2.AC代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<queue>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 1e5 + 10, MAXN = 0x3f3f3f3f;
int n, m;
int a[N], b[N], c[N], res[N];
vector<int>g[N];
int main()
{
int t;
cin >> t;
while (t--)
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) g[i].clear();
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])
g[b[i]].push_back(i);
}
for (int i = 1; i <= m; i++)
{
scanf("%d", &c[i]);
}
int last = -1;//last纪录最后一个被粉刷的地方
if (g[c[m]].size() > 0)//存在a[i]!=b[i]
{
last = g[c[m]].back();
g[c[m]].pop_back();
}
else
{
for (int i = 1; i <= n; i++)
{
if (b[i] == c[m])
{
last = i;
break;
}
}
}
if (last == -1)//给的颜色全是b中不存在的
{
puts("NO");
goto A;
}
res[m] = last;
for (int i = 1; i < m; i++)
{
if (g[c[i]].size() == 0)
{
res[i] = last;//不存在的元素,把它刷到最后一个刷的地方去
}
else
{
res[i] = g[c[i]].back();//注意是c[i],实际上是在找a[i]!=b[i]时,是否存在c[i]==b[i]
g[c[i]].pop_back();
}
}
for (int i = 1; i <= n; i++)
{
if (g[i].size() > 0)//a[i] != b[i]时,不存在c[i] == b[i]
{
puts("NO");
goto A;
}
}
puts("YES");
for (int i = 1; i <= m; i++)
{
printf("%d ", res[i]);
}
cout << endl;
A:
continue;
}
return 0;
}
如果觉得有用还请点个赞吧,拜托拜托