Codeforces Round #658 (Div. 2) E. Mastermind

E. Mastermind

题目大意:

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\n");
        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\n",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\n",l,r,res);
            while (l <= mid && r <= n && res) {
//                printf("res=%d l=%d id=%d color=%d r=%d id=%d color=%d\n",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\n");
            for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
            printf("\n");
        }
    }
}
/*
1
6 1 3
3 1 1 1 1 1

1
6 1 6
3 2 3 2 1 1
 */
posted @ 2020-07-22 20:42  EchoZQN  阅读(269)  评论(0编辑  收藏  举报