题目大意:
t组输入,给你 (n,x,y) ,其中n表示有n个数,x表示答案序列和给定的序列有x个位置值相同,y表示对答案序列重新排序最多有y个位置的值相同,在给出一个大小是n的序列,问是否存在一个满足条件的答案序列,存在则输出。
题解:
贪心。
- 先求出每一个颜色的数量,写一个结构体,存三个值,一个 (id),一个(pos),一个 (color),(id) 是为了之后排序打乱之后存答案,$ pos$ 表示当前这个是这个(color) 的第几个,(color) 就不用说了吧
- 然后按照 (pos) 从大到小排个序,注意这个和 (color) 唯一的关系就是排在越前面表示这个 (color) 的值越多。
- 为什么要这么排呢?这个是因为我们贪心的想,同一个颜色的color越少越好,这个有利于之后不同颜色的匹配,也不影响其他匹配。
- 所以按照 (pos) 排完序之后,前面的 (x)个就用来满足第一个要求。
- 之后就是一个比较简单的问题,如果接下来看不懂可以看看这个题目:Gym - 101291I,推荐题解:https://blog.csdn.net/qq_43305984/article/details/88749031
- 所以接下来就是把 (pos) 表示这个 (color) 还剩下的数,然后按照 (pos) 从大到小排个序,假设有 (n) 个,第 (i) 个和第 (frac{n}{2}+i)个匹配,和上面哪个题目一样的做法。
但是这个还是挺难写的,还有考虑一些特殊情况,比如 ((y-x)&1 \,and\, y==n) ,所以要特判。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
struct node{
int id,pos,color;
}a[maxn];
int d[maxn],ans[maxn];
bool cmp(node a,node b){
if(a.pos==b.pos) return a.color<b.color;
return a.pos>b.pos;
}
int main() {
int t;
scanf("%d", &t);
int ca=0;
while (t--) {
ca++;
int n, x, y;
scanf("%d%d%d", &n, &x, &y);
for (int i = 1; i <= n + 1; i++) d[i] = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i].color);
d[a[i].color]++;
a[i].pos = d[a[i].color];
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp);
if (x < n && 2 * (n - a[x + 1].pos - x) < y - x) printf("NO
");
else {
int f = 1;
while (d[f]) f++;
for (int i = 1; i <= n; i++) ans[i] = f;
for (int i = 1; i <= x; i++) ans[a[i].id] = a[i].color, d[a[i].color]--;
for (int i = x + 1; i <= n; i++) a[i].pos = d[a[i].color];
sort(a + 1 + x, a + 1 + n, cmp);
if ((y - x) % 2 && y == n) {
int nxt = x + 1 + a[x + 1].pos;
ans[a[x + 1].id] = a[nxt].color;
int nex = nxt + a[nxt].pos;
ans[a[nxt].id] = a[nex].color;
ans[a[nex].id] = a[x + 1].color;
d[a[x+1].color]--,d[a[nxt].color]--,d[a[nex].color]--;
for (int i = x + 1; i <= n; i++) a[i].pos = d[a[i].color];
a[x + 1].pos = a[nxt].pos = a[nex].pos = inf;
sort(a + 1 + x, a + 1 + n, cmp);
x += 3;
}
// for(int i=1;i<=n;i++) printf("i=%d color=%d pos=%d
",i,a[i].color,a[i].pos);
int mid = (x + 1 + n) / 2;
int l = x + 1, r = max(mid + 1, x + 1 + a[x + 1].pos), res = y - x;
// printf("l=%d r=%d res=%d
",l,r,res);
while (l <= mid && r <= n && res) {
// printf("res=%d l=%d id=%d color=%d r=%d id=%d color=%d
",res,l,a[l].id,a[l].color,r,a[r].id,a[r].color);
if (res) ans[a[l].id] = a[r].color, res--;
if (res) ans[a[r].id] = a[l].color, res--;
l++, r++;
}
printf("YES
");
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
printf("
");
}
}
}
/*
1
6 1 3
3 1 1 1 1 1
1
6 1 6
3 2 3 2 1 1
*/