AtCoder Beginner Contest 194 E - Mex Min

Probably the meaning of the question:

Give one not more than 1.5 × 1 0 6 1.5\times10^61.5×10Array of 6 A 1 A_1A1To A i A_iAiLength in mmm , and annn , give each consecutivennThe smallest number among the smallest numbers that do not appear in n numbers.

Ideas:

Don't you just slide the window as soon as you look at this question (there is a detailed explanation here)! ! ! After pasting on the other oj, I changed it and handed it in directly. As a result, I
Insert picture description here
looked at the question again and noticed that as long as it is the smallest number among the numbers that did not appear. The data is not big, nn before opening an array recordThe number of occurrences of each of the n numbers and find the smallest number among the numbers that do not appear, then the double pointer points one at the end and the other at the end, each time theA tail is A_tailATailThe number of occurrences of is reduced by one, A head A_ headAHeadAdd one to the number of occurrences to determine the end of A and the end of A_ATailWhether the number of occurrences is 0, if it is 0, compare it with the previously recorded minimum value. If the current minimum value that has not appeared is smaller than the minimum value that has not appeared before, the minimum value that has not appeared before must be in the queue. in.
Let’s put it this way, let’s take a more intuitive example of my hand

Input

7 3
2 0 1 2 0 1 0

Output

2
Insert picture description here
So the output answer is 2, which is intuitive enough, and because A i A_iAiNo more than 1.5 × 1 0 6 1.5\times10^61.5×106 , and it is more than enough to open such a large array.

Code

#include <bits/stdc++.h>
using namespace std;
const int N=2e6;
int num[N],a[N],n,k,ans=9999999;
bool flag;
void work()
{
    
    
	int head=k,tail=1;
	for(int i=tail;i<=head;i++)
	{
    
    
		num[a[i]]++;
	}
	for(int i=0;;i++)
	{
    
    	
		if(num[i]==0)
		{
    
    
			ans=min(ans,i);
			if(ans==0)
			{
    
    
				cout<<0;
				flag=1;
				return;
			}
			break;
		}
	}	
	while(head<n)
	{
    
    
		num[a[tail]]--;
		tail++;
		num[a[head]]++;
		if(num[a[tail]]==0)
		{
    
    
			ans=min(ans,a[tail]);
		}
		head++;
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	work();
	if(flag==0)
		cout<<ans;
	return 0;
}

Then WA had 5 groups of dead and alive and couldn't change it. After playing the game, I sent it to the seniors of the second grade to take a look. It was found that the seniors of the second and third grades used the tree array, the chairman tree and the line segment tree water respectively. Here is the code for the tree array:
I can’t understand it, so I won’t explain it

#include<bits/stdc++.h>
#define N 1600006
#define LL long long 
#define LB long double
using namespace std;

int n,m;
int ans=1e8,a[N],sp=0;
int mp[N],tr[N];

inline int qr()
{
    
    
	char a=0;int w=1,x=0;
	while(a<'0'||a>'9'){
    
    if(a=='-')w=-1;a=getchar();}
	while(a<='9'&&a>='0'){
    
    x=(x<<3)+(x<<1)+(a^48);a=getchar();}
	return x*w;
}

const int K=1500002;

inline void add(int x,int k)
{
    
    
	for(register int i=x;i<=K;i+=i&-i) tr[i]+=k;
}

inline int que(int x)
{
    
    
	int res=0;
	for(register int i=x;i;i-=i&-i) res+=tr[i];
	return res;
}

int jac[123];
inline int ask()
{
    
    
	int pos=1;
	for(register int i=21;i>=0;i--)
		if(pos+jac[i]-1<=K)
		{
    
    
			int op=que(pos+jac[i]-1);
			if(op==pos+jac[i]-1)
				pos+=jac[i];
		}
	return pos;
}

int main()
{
    
    
	n=qr();
	m=qr();
	jac[0]=1;
	for(register int i=1;i<=21;i++) jac[i]=jac[i-1]<<1;
	for(register int i=1;i<=n;i++) a[i]=qr()+1;
	for(register int i=1;i<=n;i++)
	{
    
    
		mp[a[i]]++;
		if(mp[a[i]]==1) add(a[i],1);
		if(i>=m)
		{
    
    
			ans=min(ans,ask());
			mp[a[i-m+1]]--;
			if(!mp[a[i-m+1]]) add(a[i-m+1],-1);
		}
	}
	printf("%d\n",ans-1);
	return 0;
}

Written by this god

Then my code was simplified a bit after I changed it

#include <bits/stdc++.h>
using namespace std;
const int N=2e6;
int num[N],a[N],n,k,ans=9999999;
bool flag;
void work()
{
    
    
	int tou=1,wei=k;
	for(int i=1;i<=k;i++)num[a[i]]++;
	for(int i=0;;i++)
	if(num[i]==0){
    
    ans=i;break;}
	if(ans==0)return;
	while(wei<n){
    
    
		num[a[++wei]]++;
		num[a[tou]]--;
		if(num[a[tou]]==0)
		ans=min(ans,a[tou]);
		tou++;
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	work();
	cout<<ans;
	return 0;
}

In fact, the main reason is that my tail end point moved early, so I should first judge whether a tail is a_tailaTailWhether the number of occurrences is 0 00 then let the tail move.
Well, that's it. This is the easiest E question in AtCOder's ABC, but the mistake in the exam made me miss 500 points. Gan, this reminds me ofthe T1 of theprevious simulation game.Iwas going to write memoization, but the reverse of x and y caused the array to cross the boundary. The maximum result of the legal situation in the problem, I found the maximum process in the legal situation the amount.
Insert picture description here

Guess you like

Origin blog.csdn.net/ydsrwex/article/details/114528520