C. MEX Repetition

Topic: Example:

enter
5
1 2
1
3 1
0 1 3
2 2
0 2
5 5
1 2 3 4 5
10 100
5 3 0 4 2 1 6 9 10 8

output
1
2 0 1
2 1
2 3 4 5 0
7 5 3 0 4 2 1 6 9 10

Idea:

        From the questions and examples, we can know that from an array, find an exact order in the order of natural numbers including 0, and then exchange them from left to right. After clarifying the ideas and ideas, violent simulation will definitely not work. The data range is too large. The data range of k is 1e9, the data range of n is 1e5, and the data range of t is added to 1e5. If it is pure violence, according to the worst In this case, the time complexity is about 10 to the 19th power. So basically impossible.

        We can look at the example and find a rule, that is, the missing natural number x including 0 for the first time will be removed from the front or back in the output sample, and then the x will be placed in front or behind. We can guess and know that after a certain exchange, the effect may be the same as the previous one, that is, according to the length n, k % n + 1 operations have the same effect as k operations, here k % n + 1 When k % n is exactly divisible, k operations should be valid, that is, there is at least one valid operation, so k % n + 1 can shorten the data range of k and shorten the time complexity. Secondly, x is not The front is the back, and the basic order in the middle will not change. We can guess, and it is somewhat close to the operation properties of the front and rear queues. It is estimated to be the operation of a double-ended queue.

        That is, place the back end on the front end k % n + 1 times, and then output the queue sequentially according to the number of original arrays.

The code is explained in detail below:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;

inline void solve()
{
	int n,k,x = 0;
	cin >> n >> k;
	
	// 存储双端队列
	deque<int>q;
	
	// 标记数组中的包括0自然数是否出现过
	umap<int,bool>r;
	
	for(int i = 0,num;i < n;++i)
	{
		cin >> num;
		
		// 按照顺序存储好原数组
		q.push_back(num);
		
		// 标记好出现过的包括0自然数
		r[num] = true;
		
		// 寻找按照顺序没出现过的包括0自然数
		while(r[x]) ++x;
	}
	
	// 存储好 x 在尾端,然后根据 k 进行放前端
	q.push_back(x);
	
	// k 次操作 与 k %= n + 1 次操作效果相同
	// 有效缩短时间复杂度
	k %= n + 1;
	
	// k 次操作 队列,将尾端放置前端
	while(k--)
	{
		q.push_front(q.back());
		q.pop_back();
	}
	
	// 按照原个数,顺序输出操作完后的数组
	while(n--)
	{
		cout << q.front() << ' ';
		q.pop_front();
	}
	cout << endl;
}
int main()
{
//	freopen("a.txt", "r", stdin);
	___G;
	int _t = 1;
	cin >> _t;
	while (_t--)
	{
		solve();
	}
	return 0;
}

Last commit:

Guess you like

Origin blog.csdn.net/hacker_51/article/details/133429315