題目大意:
每次都會往你的數列里加一個值,你可以任意加減這個值若干次(但是只能加x或者減x)
然后問最小的不屬於這個數列的非負整數是什么
你需要進行的操作是,讓這個最小的不屬於這個數列的非負整數最大
每次加一個值並且詢問一遍
解題思路:
易得到,每一次輸出的答案在進行完題目的貪心后會呈現上升趨勢,且值最大只可能為序列內元素的個數
所以我們可以讓每次加入的值在進行完若干次操作后盡量成為靠前的序列中還沒出現過的數值,以助於答案能盡量變得更大
舉題目的樣例,不能按照Hint的思想去想,根據上述思想可以得到下面的步驟——
q=7,x=3
加入0,序列為[0],答案為1
加入1,序列為[0,1],答案為2
加入2,序列為[0,1,2],答案為3
加入2,因為2存在過,所以貪心讓2變成盡量靠前的未出現的數,即5,所以序列為[0,1,2,5],答案為3
加入0,因為0存在過,所以貪心讓0變成盡量靠前的未出現的數,即3,序列為[0,1,2,3,5],答案為4
加入0,因為0存在過,貪心讓0變成盡量靠前的未出現的數,又因為3也出現過,所以為6,序列為[0,1,2,3,5,6],答案為4
加入10,10未出現過,變成盡量靠前的未出現的數,可得能夠變成4,序列為[0,1,2,3,4,5,6],答案為7
經過以上操作,可以發現一個規律
不管怎么讓新加進來的值d怎么變(+x/-x),d%x的值保持不變
所以可以想到用一個數組mini存不同的d%x這一類數字此時最小的未出現過的值
其后每次加進來一個值d,取mini[d%x]讓這個數加進當前的序列內,然后讓mini[d%x]+x成為下一個未出現過的數即可
如果mini[t]>q了,說明這一類的數字太多了,再加對答案也不會有貢獻,就可以不考慮了
然后讓答案作為一個變量,因為答案只增不減,每次就保持它的狀態即可,在可以嘗試增大時用
while(arr[ans])ans++;
來讓他增大即可(arr數組判斷數是否存在於序列內)
#include<bits/stdc++.h> using namespace std; bool arr[400050];//判斷i是否存在於當前的數列內 int mini[400050];//d%x的種類之下未出現在arr序列中的最小數 void solve(){ int q,x,d,t,i,ans=0; cin>>q>>x; for(i=0;i<x;i++) mini[i]=i; for(i=0;i<q;i++){ cin>>d; t=d%x; if(mini[t]<q){ arr[mini[t]]=true; while(arr[ans]) ans++; mini[t]+=x; } cout<<ans<<'\n'; } } int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); solve(); return 0; }
或者簡化下代碼,意思不變,此時只要多進行取模運算即可
#include<bits/stdc++.h> using namespace std; int arr[400050]; void solve(){ int q,x,d,t,i,ans=0; cin>>q>>x; while(q--){ cin>>d; arr[d%x]++; while(arr[ans%x]){ arr[ans%x]--; ans++; } cout<<ans<<'\n'; } } int main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); solve(); return 0; }