• 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
    ");
            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
     */
    
  • 相关阅读:
    内置函数拾遗
    jQuery与其他JS库冲突解决
    ckeditor+ckfinder添加水印。
    PostgreSQL与mysql的比较
    php函数 之 iconv 不是php的默认函数,也是默认安装的模块。需要安装才能用的。
    php mb_substr()函数的详细解释!
    成为一名PHP专家其实并不难
    php中级程序员的进化标准
    鼠标经过图片切换效果。
    计算两个日期之间的工作日
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13362999.html
Copyright © 2020-2023  润新知