给定一个长度为 N 的数组 A=[A1,A2,⋅⋅⋅AN],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。
小明会依次修改 A2,A3,⋅⋅⋅,AN。
当修改 Ai 时,小明会检查 Ai 是否在 A1∼Ai−1 中出现过。
如果出现过,则小明会给 Ai 加上 1;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1,直到 Ai 没有在 A1∼Ai−1 中出现过。
当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。
现在给定初始的 A 数组,请你计算出最终的 A 数组。
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,⋅⋅⋅,AN。
输出格式
输出 N 个整数,依次是最终的 A1,A2,⋅⋅⋅,AN。
数据范围
1≤N≤105,
1≤Ai≤106
输入样例:
5
2 1 1 3 4
输出样例:
2 1 3 4 5
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<climits>
using namespace std;
int n;
typedef pair<int, int> PII;
set<PII> sgs;
int main() {
int x;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &x);
if (i == 0) {
sgs.insert({ x,x });
printf("%d ", x);
continue;
}
//在集合中去找一个区间包含x的,本来我们只需要找一个数x,但是由于set里面存的区间,一个数和一个区间肯定无法直接比较大小,所以我们要把这个数x变成一个区间,即<x,INT_MIN>,就可以用lower_bound查找了,找到的是第一个大于或等于这个pair的pair(pair先比较第一个关键字的大小。如果相等,再比较第二个关键字的大小)。
//二分查找包含x的区间
auto it = sgs.lower_bound(PII(x, INT_MIN));
//如果包含 即[*,?] (?>=x)
if (it != sgs.end() && it->second <= x) {
//printf("包含\n");
//修改x为这个区间的右端点+1,即让x脱离这个区间。
x = it->first + 1;
//合并这两个区间,且必然能合并
int l = it->second;//备份区间左值
sgs.erase(it);//删除原来的区间
sgs.insert(PII(x, l));//插入新的区间
//我们去找一个区间的右端点大于等于x+1
//即[3,x]->[?,?] (?>=x+1)
it = sgs.lower_bound({ x,l });
auto back = sgs.lower_bound(PII(x+1, INT_MIN));
if (back != sgs.end() && back->second == x + 1) {
//如果找到了这样的一个pair(右端点大于x,左端点等于x+1)
//那么这两个区间又可以合并了
int r = back->first;
int l = it->second;
sgs.erase(it);
sgs.erase(back);
sgs.insert(PII(r, l));
}
}
else {
//没有一个区间包含x,那么x就不需要修改
//先插入到set里面
sgs.insert(PII(x, x));
//检查是否可以合并 [?,x-1],[x,x],[x+1,?]
//找右端点大于等于x-1的
auto it = sgs.lower_bound(PII(x, x));//先定位
auto pre = it;
if (pre != sgs.begin()) {
pre--;
if (pre->first + 1 == it->second) {
//合并
int l = pre->second;
int r = it->first;
sgs.erase(pre);
sgs.erase(it);
sgs.insert({ r,l });
}
}
//定位[?,x]
it = sgs.lower_bound(PII(x, INT_MIN));
auto back = sgs.lower_bound({ x + 1,INT_MIN });
if (back != sgs.end() && back->second == it->first + 1) {
//合并
int l = it->second;
int r = back->first;
sgs.erase(it);
sgs.erase(back);
sgs.insert(PII(r, l));
}
}
printf("%d ", x);
}
printf("\n");
return 0;
}