题意: 给你一个长度为 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; }