第十五届蓝桥杯省赛第二场C/C++B组C题【传送阵】题解(AC)



解题思路

由于 a a a 数组是一个 1 1 1 到 n n n 的一个排列,那么形成的一定是如下形式:

一定会构成几个点的循环,或者是几个单独的点。

从任意点开始,如果能进入一个循环,一定可以将整个循环的宝藏都拿走,因为不限进入传送门的次数。

那么,我们可以用并查集来维护点与点之间的关系,以及一个小团体里头点的数量。

由于我们可以使用一次从 j j j 跳到 j − 1 j - 1 j−1 或 j + 1 j + 1 j+1 的位置,那么我们可以枚举所有的 c n t f i n d ( j ) + c n t f i n d ( j + 1 ) cntfind(j) + cntfind(j + 1) cntfind(j)+cntfind(j+1),其中 f i n d ( j ) ≠ f i n d ( j + 1 ) find(j) \neq find(j+1) find(j)=find(j+1)。

时间复杂度约为 O ( n ) O(n) O(n)。

cpp 复制代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 1e6 + 10;

int n;
int p[N], cnt[N];

int find(int x)
{
    if (x != p[x])
        p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; ++ i )
        p[i] = i, cnt[i] = 1;
    
    for (int i = 1; i <= n; ++ i )
    {
        int x;
        cin >> x;
        int a = find(i), b = find(x);
        if (a == b)
            continue;
        cnt[a] += cnt[b];
        p[b] = a;
    }
    
    int res = 0;
    for (int i = 1; i < n; ++ i )
    {
        int a = find(i), b = find(i + 1);
        if (a == b)
            res = max(res, cnt[a]);
        else
            res = max(res, cnt[a] + cnt[b]);
    }
    
    cout << res << endl;
    
    return 0;
}

【在线测评】

相关推荐
程序喵大人2 小时前
【C++入门】编译链接模型 - 01 一个 C++ 程序是怎样变成可执行文件的
开发语言·c++·编译链接模型
by209993 小时前
vector 的模拟实现:扩容与边界的详细阐述(下)
c++·经验分享·vector·动态数组
余额瞒着我当琳6 小时前
红黑树的实现--红黑树的概念、规则、效率、结构、旋转、查找、验证
数据结构·c++·算法
青少儿编程课堂6 小时前
AC自动机多模式串匹配精讲:校园关键词巡检实战解析
c++·python·算法·bfs·信息学竞赛
longlongzihan7 小时前
LeetCode 5. 最长回文子串:从暴力匹配到中心扩展的思维演进
c++·算法·leetcode
多弗朗皮卡丘7 小时前
C++继承
c++·继承
Escalating_xu8 小时前
【C 语言】深入理解指针(4):回调函数、qsort、void * 与泛型排序的模拟实现
java·c语言·开发语言
汉克老师8 小时前
GESP2026年9月认证C++七级( 第三部分编程题(2、括号序列))精讲
c++·gesp·小学生·学c++编程
吠品8 小时前
GitHub 周榜拆解:决策小模型扎堆上位
c语言·开发语言·算法
小师兄吃牛肉9 小时前
C语言篇:内联函数
c语言·开发语言