CF2123E 题解
这题真比 CD 简单吧。
直接求是比较困难的,我们考虑换个角度。
考虑枚举
以样例的第一组数据举例。
5
1 0 0 1 2
我们假定答案数列都先为
当 0 0,1 0 0,0 0 1,0 0 2,1 0 0 1,1 0 0 2,0 0 1 2,1 0 0 1 2。删除
接着我们有定理:不论
就如上面的“删除
考虑证明。
假设当前的
根据
这说明所有
显然,我们能决定是否删去的只有可删可不删的。
而可删可不删的数字数量是固定的。所以删一个、删两个、删三个……直到删完都是符合题意的。
这样,我们删除数字的总数就是必删的数量加上我们选择的可删可不删的数量。后者是连续的,前者是不变的。总数必然也是连续的。
证明结束。这样我们就把问题转化成了多次区间加的问题。
区间左端点是必删的数量,右端点是必删的数量加上所有可删可不删的数量,即
用一个桶就可以知道必删的数量。
最后由于删数后
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 55;
int n, a[N], b[N], c[N];
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int TTT;
cin >> TTT;
while (TTT--) {
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> a[i];
b[a[i]]++;
}
int MEX = 0;
for (int i = 0;i <= n;i++) {
if (b[i] == 0) {
MEX = i;
break;
}
}
for (int i = MEX;i >= 0;i--) {
c[b[i]]++;
c[n - i + 1]--;
}
for (int i = 0;i <= n;i++) {
if (i >= 1) c[i] += c[i - 1];
cout << c[i] << " ";
}
cout << "\n";
for (int i = 0;i <= n + 1;i++)
a[i] = b[i] = c[i] = 0;
}
return 0;
}