zoukankan      html  css  js  c++  java
  • 蓝桥杯 修改数组 (巧用并查集)

    题意: 给你一个长度为 n 的序列, 现在按以下方法修改序列: 

           1、依次修改 A1 A2 A3 A4 A5 ...... AN;

         2、当修改 Ai 时, 检查 A1 ~ Ai-1 是否出现过, 若出现过, 则Ai加1,若更新完的Ai仍然在A1 ~ Ai 出现过, 则继续加1,直到未出现过。

         输出最终序列。 1 <= n <= 100000,   1 <= Ai <= 1000000

    解:  巧用并查集。  

        f[ i ] 表示当你访问到 i  这个数时 应该将它 换成什么。 

        一开始的时候 f[ i ] 都等于 i, 因为都还没被访问过。

       当你访问完 i 这个数, 你需要更新它的 f[ i ] 为 f[ i + 1 ];

       因为, 当你再次访问到 i 的时候, i 已经输出过了, 所以你需要输出 i + 1;

       但,你可能 i + 1也出现过了, 所以你 输出的是 f[ i + 1];

       

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define INF 0x3f3f3f3f
    #define inf 0x3f3f3f3f3f3f3f3f
    #define mem(i, j) memset(i, j, sizeof(i))
    #define pb push_back
    using namespace std;
    
    const int N = 1e6 + 5;
    int f[N], a[N];
    int Fin(int v) {
        return f[v] == v ? v : f[v] = Fin(f[v]);
    }
    
    int main() {
        rep(i, 1, N - 1) f[i] = i;/// 初始化, 指向自己
        int n; scanf("%d", &n);
        rep(i, 1, n) {
            scanf("%d", &a[i]);
            int nx = Fin(a[i]); /// 当前这个点, 指向的点
            a[i] = nx;
            f[a[i]] = Fin(a[i] + 1); /// 这个点,更新为下一个点指向的点
        }
        rep(i, 1, n - 1) printf("%d ", a[i]);
        printf("%d
    ", a[n]);
        return 0;
    }
    View Code
    一步一步,永不停息
  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/Willems/p/12005032.html
Copyright © 2011-2022 走看看