这是一道神奇的求前缀mex然后拿出来并且使得拿出来的数组的字典序最大,神奇的一道题,基础思路是去用权值(甚至去学了学)线段树去找出每个区间内的mex,后来发现这个个题的数据十分的小,所以就觉得将数据存在桶里面然后遍历过后再把它给在桶里面的给减去,然后下一个找他的下一个的桶里有没有数据,如果有就继续找,如果没有的话,当前最大的mex就是当前的值,最后记录一下这个过程产生的值即可
题目:
ac代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 2e5 + 10;
typedef long long int LL ;
int a[N];
int num[N];
int now[N];
int n ;
int r ;
void find()
{
while(now[r] && r <= n)r ++ ;
// for(int i = 0 ; i <= n ; i ++)cout << now[i]<<' ';
// cout <<endl;
}
int main()
{
ios :: sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--)
{
cin >> n ;
for(int i = 0 ; i <= n+1 ; i ++)num[i] = now[i] = 0;
for(int i = 1; i <= n ; i ++)cin >> a[i],num[a[i]]++;
// for(int i = 0 ; i <= n ; i ++)cout << num[i]<<' ';
// cout <<endl;
vector<int> ans;
r = 0 ;
for(int i = 1; i <= n ; i ++)
{
find();
// cout << i <<' '<< r <<' '<<num[r]<<endl;
if(!num[r])
{
int temp = r;
for(int j = 0 ; j <= r ; j ++)now[j] = 0 ;
ans.push_back(r);
r = 0 ;
if(!num[r] && r != temp)
{
ans.push_back(0);
continue;
}
}
if(num[r])
{
int j = i ;
while(j <= n && a[j] != r)
{
num[a[j]]--;
now[a[j]]++;
j ++ ;
}
if(a[j] == r)num[a[j]]--,now[a[j]]++;
i = j ;
}
}
find();
if(r)ans.push_back(r);
cout << ans.size()<<endl;
for(auto it : ans)cout << it <<' ';
cout <<endl;
}
return 0 ;
}