许可优化
产品
解决方案
服务支持
关于
软件库
当前位置:服务支持 >  软件文章 >  Codeforces Round #842 (Div. 2) C贪心D置换群:解题攻略

Codeforces Round #842 (Div. 2) C贪心D置换群:解题攻略

阅读数 3
点赞 0
article_banner

C.Elemental Decompress

原题连接

Problem - C - Codeforces

题目标签

贪心

题目描述

给定一个长度为n的数组 num_1,num_2,num_3 \dots num_n

问是否有两个长度为 n的全排列 p q满足

num[i]=max(p[i],q[i])

若有输出YES并打印数组

若没有输出NO

题目解析

特判

首先包括以下几种特判

  • 最大数 n 至少出现 1
  • 1只能出现 1次,其余每个数最多出现 2

常规

考虑贪心,先对数组进行排序

排序后

上下两个排列,用set来存储还可以使用的值


遍历数组如下:

每一个数 num[i]让下面的先选

其实上下无所谓,先让一方选即可
  • 下面可以选,则选中该数,让待选列表去除该数,同时上面选其可选列表的最小值
  • 下面不可选,则让上面选中该数,让待选列表去除该数,同时下面选其可选列表的最小值
  • 两边都选不了,则说明无解输出NO
动图封面
算法过程

选中下方代码如下,选中上方则 ab 反一下

ansb[i]=num[i];//下方选num[i]
sb.erase(num[i]);//下方待选列表删除num[i]

ansa[i]=*sa.begin();//上方选待选列表最小值
sa.erase(sa.begin());//上方待选列表删除最小值

注意

排完序后,位置i不再是原来的位置i

所以这里用一个结构体存储值和下标再复制

ansb[num[i].id] = num[i].v;
sb.erase(num[i].v);

ansa[num[i].id] = *sa.begin();
sa.erase(sa.begin());

通过代码

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 201000
using namespace std;
int ansa[N];
int ansb[N];
struct node
{
    int v;
    int id;
} num[N];

bool cmp(node a, node b)
{
    return a.v < b.v;
}

void solve()
{
    int n;
    cin >> n;
    set<int> sa, sb;
    map<int, int> mp;
    bool f = true;
    for (int i = 1; i <= n; i++)
    {
        cin >> num[i].v;
        num[i].id = i;

        sa.insert(i);
        sb.insert(i);

        mp[num[i].v]++;
        if (mp[num[i].v] > 2)
        {
            f = false;
        }
    }

    /* 特判 */
    if (mp[1] > 1 || mp[n] == 0 || f == false)
    {
        cout << "NO\n";
        return;
    }

    sort(num + 1, num + 1 + n, cmp);
    for (int i = 1; i <= n; i++)
    {

        if (sb.find(num[i].v) != sb.end()) // 选下面的
        {
            ansb[num[i].id] = num[i].v;
            sb.erase(num[i].v);
            ansa[num[i].id] = *sa.begin();
            sa.erase(sa.begin());
        }
        else if (sa.find(num[i].v) != sa.end()) //选上面的
        {
            ansa[num[i].id] = num[i].v;
            sa.erase(num[i].v);
            ansb[num[i].id] = *sb.begin();
            sb.erase(sb.begin());
        }
        else //都选不到无解
        {
            cout << "NO\n";
            return;
        }
    }

    cout << "YES\n";
    for (int i = 1; i <= n; i++)
    {
        cout << ansa[i] << " ";
    }
    cout << "\n";
    for (int i = 1; i <= n; i++)
    {
        cout << ansb[i] << " ";
    }
    cout << "\n";
}

signed main()
{
    ios;
    int T;
    T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
}

D.Lucky Permutation

置换群 不会

明天会了再更


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删
相关文章
QR Code
微信扫一扫,欢迎咨询~

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 155-2731-8020
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

手机不正确

公司不为空