2021 第45届icpc昆明站 J题 Parallel Sort 题解

该博客探讨了一种全排列数字的交换操作问题,通过构建环并分析环的大小来确定最少交换次数。文章提供了C++代码实现,展示了如何在不超过两次操作的情况下达到有序状态,并给出了具体的操作序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目(Problem):

题目通道题目截图

题目大意(The meaning fo the problem):

给出一个组全排列数字,每次操作可以对排列中任意两个数交换,要求每次交换不重复使用某一个数字。输出需要的次数和每次的操作。

题目思路(The method of solving):

构建环。对于a[i]找到a[a[i]]连环,由于是全排列最后一次肯定找到第一个a[i]
对于某一个环,最多只需要两次操作。所以操作只有可能是0,1,2次。
对于一个长度大于2的环,将环拆分成n/2个只有2个点的环,最后再执行一次交换则变为有序。

代码(Code):

#include "bits/stdc++.h"
#define endl "\n"

using namespace std;
const int MAXN = 1e5 + 5;

int a[MAXN];
vector<int>ans, ans2;
bool flag[MAXN] = {0};

int main(void) {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", a + i);
    }
    for (int i = 1; i <= n; ++i) {
        if (a[i] != i) break;
        if (i == n) {
            cout << 0 << endl;
            return 0;
        }
    }
    bool isOne = true;
    for (int i = 1; i <= n; ++i) {
        if (flag[i]) continue;
        int x = i;
        vector<int>temp;
        while (!flag[x]) {
            temp.push_back(x);
            flag[x] = true;
            x = a[x];
        }
        //cout << temp.size() << ' ' << temp[0] << endl;
        if (temp.size() == 2) {
            ans.push_back(temp[0]);
            ans.push_back(temp[1]);
        }else {
            for (int l = 1, r = temp.size() - 1; l < r; l++, r--) {
                ans.push_back(temp[l]);
                ans.push_back(temp[r]);
                swap(temp[l], temp[r]);
            }
            for (int l = 0, r = temp.size() - 1; l < r; l++, r--) {
                ans2.push_back(temp[l]);
                ans2.push_back(temp[r]);
            }
            isOne = false;
        }
    }
    if (isOne) {
        cout << 1 << endl;
    }else {
        cout << 2 << endl;
    }
    cout << ans.size() / 2;
    for (auto it : ans) {
        cout << ' ' << it;
    }
    cout << endl;
    if (!isOne) {
        cout << ans2.size() / 2;
        for (auto it : ans2) {
            cout << ' ' << it;
        }
        cout << endl;
    }

    return 0;
}
<think>嗯,用户想要找2024年ICPC昆明邀请赛的目解析,但根据提供的引用内容,现有的资料只覆盖到2022年昆明目,比如引用[1]提到2020、2021年的ICPC和CCPC目,以及引用[4]详细解析了2022昆明的G。不过用户询问的是2024年的,这可能还没有公开的解析,或者可能还没有举办。需要先确认是否存在2024年的比赛信息,或者是否用户可能记错了年份?比如,2024年的比赛可能尚未举行,或者相关信息还未被整理发布。 首先,检查提供的引用内容,发现最新的昆明信息是2022年的,引用[4]讨论的是2022昆明G。用户提到的2024年可能是个错误,或者他们希望提前获取信息。但通常比赛结束后才会有解析,所以需要告知用户目前没有相关资料,并建议他们关注官方渠道或后续的社区分享。同时,可以推荐现有的2022年昆明题解作为参考,帮助用户了解型和考点,比如动态规划、期望计算等常见问。 另外,用户可能对如何准备比赛感兴趣,可以建议他们分析历年目类型,比如引用[1]提到的区域赛常考型,或者引用[3]中提到的训练经验。需要确保回答准确,避免提供不存在的资源,同时提供有用的替代信息,帮助用户找到最近的可用资料。</think>关于2024年ICPC昆明邀请赛目解析,目前尚未有官方或主流平台发布完整的目解析报告。根据历史信息推测,ICPC区域赛的目解析通常会在赛后由参赛队伍、算法社区或教练团队逐步整理发布。以下是可参考的备赛建议和现有资源: --- ### 一、近期ICPC型趋势参考 1. **动态规划与组合数学** 如2022年昆明G考察了**概率期望与递推关系**,需掌握马尔可夫链、状态转移方程的建立[^4] $$E = \sum_{i=1}^n \left( \frac{p_i}{1-p_i} \cdot \sum_{j \neq i} \frac{p_j}{1-p_i} \right)$$ 此类问常需分析极限状态下的数学期望。 2. **数据结构优化** 近年区域赛常出现需要**线段树/树状数组维护区间性质**的目,例如区间最值、历史版本查询等。 3. **图论与网络流** 包括最小割建模、分层图最短路等高级技巧,如2021年沈阳曾出现网络流与二分答案结合的目[^2]。 --- ### 二、获取解析的途径建议 1. **官方渠道** 关注ICPC官网及昆明承办院校的赛事公告,解析可能通过**赛后题解报告会**发布。 2. **算法社区** - **Codeforces**:搜索标签`[ICPC Kunming 2024]` - **知乎/掘金**:技术博主常撰写详细题解(例:2022年G推导过程) 3. **训练平台** 尝试在**Codeforces Gym**或**牛客竞赛**库中查找昆明模拟赛。 --- ### 三、历昆明参考 若需练习类似型,可参考2022年昆明目: - **G(豆子操作期望)**:结合概率论与递推,需推导稳定状态下的位置关系 - **B(几何构造)**:通过坐标系变换简化多边形切割问 ```python # 示例:概率期望计算的代码框架 def calculate_expected_value(probabilities): n = len(probabilities) expected = 0.0 for i in range(n): pi = probabilities[i] term = pi / (1 - pi) if pi != 1 else 0 sum_other = sum(pj / (1 - pi) for j, pj in enumerate(probabilities) if j != i) expected += term * sum_other return expected ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值