ABC 272 E Add and Mex(调和级数 暴力)
E Add and Mex(调和级数 暴力)
题意:
给出一个长度为n\(\le 1e5\)的数组a,每秒对数组中的数加上其下标,例如\(a_i\)在第一秒为\(a_i+i\),第二秒为\(a_i+2i\)。请输出前m\(\le 1e5\)秒中每一秒的最小的非负整数。
思路:
因为只有n个数,那么这个最小非负整数一定小于\(1e5\)。那么当\(a_i\)大于1e5的时候就没有用了,这点很重要。那么我们直接去暴力枚举,把结果存在\(vector<int> flag[秒数]\)中,这个复杂度是调和级数也就是\(O(nlogn)\)的,轻松可以跑过。但是要注意的是,很可能会出现全是-1e9的极端情况,那你枚举的秒数的起点就需要对于这一点作出特判,详情看代码。
实现:
const int N = 200005;
int n, m;
int a[N];
vector<int> flag[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
{
if(a[i] > n) continue;
int st;
if(a[i] < 0)
st = (abs(a[i]) / i);
else
st = 1;
for(int j = st; j <= m; j ++)
{
if(a[i] + j * i < 0) continue;
if(a[i] + j * i > n) break;
flag[j].push_back(a[i] + j * i);
}
}
for (int i = 1; i <= m; i++)
{
vector<bool> vis(N, 0);
for(auto x : flag[i])
if(x < N)
vis[x] = 1;
int res = 0;
while(vis[res])
res ++;
cout << res << '\n';
}
}