Add and Mex

Problem Statement

You are given an integer sequence A=(A_1,A_2,\ldots,A_N)A=(A1​,A2​,…,AN​) of length NN.

Perform the following operation MM times:

  • For each i\ (1\leq i \leq N)i (1≤i≤N), add ii to A_iAi​. Then, find the minimum non-negative integer not contained in AA.

Constraints

  • 1\leq N,M \leq 2\times 10^51≤N,M≤2×105
  • -10^9\leq A_i\leq 10^9−109≤Ai​≤109
  • All values in the input are integers.

题目大意是有一串数字,每一轮会给每个数字加上自身号次对应的数字,需要找出每一轮这些数字中没有出现过的最小的非负整数。

一开始当然是直接想到了最暴力的方法,直接模拟每一轮然后找数字,当然是肯定不行的,所以直接看了别人的,发现需要用到一点预处理的思路。

首先要知道符合条件的数字一定在[0,n]这个区间之内,因为最坏的情况是n个数字按照公差为1的等差数列排列,这时候要么是0,要么是n,其他情况一定是在区间(0,n)里面的数字,所以我们只要考虑每个数字在这个区间内的情况。

所以对于任意的一轮,需要只要考虑所有可以落在这个区间内的数字的情况,所以在一开始的预处理,我们就需要把每个数字作为有效值出现在某一轮的值记录下来,比如n为10,a[7]为-2,那么a[7]的有效值是5(在[0,10]之内的值),出现在第一轮,那么第一轮的5就需要标记为有(利用set实现)。

预处理之后,留下的数据量其实就比较小了,对于任意的a[i],实际上有效的数字个数是n/i,最终在每一轮开始从0开始找,找到没出现的就直接输出结果就好。

代码如下:

#include
#include
#include
using namespace std;
#define ll long long
int a[2000000];
setst[500000];
int main()
{
	int m,n;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", a + i);
	//先维护
	for (int i = 1; i <= n; i++)
	{
		//先看在m轮里面这个数字能不能落在[0,n]
		int num = 0;//表示贡献的轮数
		if (a[i] < 0)
		{
			num += ((-a[i]) - 1) / i + 1;
			a[i] += num * i;
		}
		while (num <= m && a[i] <= n)
		{
			st[num].insert(a[i]);
			a[i] += i;
			num++;
		}
	}
	//开始查找
	for (int i = 1; i <= m; i++)
	{
		for (int j = 0; j <= n; j++)
		{
			if (!st[i].count(j))
			{
				//表示数字为0
				printf("%d\n", j);
				break;
			}
		}
	}
	return 0;
}#include
#include
#include
using namespace std;
#define ll long long
int a[2000000];
setst[500000];
int main()
{
	int m,n;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", a + i);
	//先维护
	for (int i = 1; i <= n; i++)
	{
		//先看在m轮里面这个数字能不能落在[0,n]
		int num = 0;//表示贡献的轮数
		if (a[i] < 0)
		{
			num += ((-a[i]) - 1) / i + 1;
			a[i] += num * i;
		}
		while (num <= m && a[i] <= n)
		{
			st[num].insert(a[i]);
			a[i] += i;
			num++;
		}
	}
	//开始查找
	for (int i = 1; i <= m; i++)
	{
		for (int j = 0; j <= n; j++)
		{
			if (!st[i].count(j))
			{
				//表示数字为0
				printf("%d\n", j);
				break;
			}
		}
	}
	return 0;
}

你可能感兴趣的:(c++,算法)