Codeforces Round #673 (Div. 2)C. k-Amazing Numbers
题意
给你一个长度为n的数组,让你找到以i为长度的子段中都出现的最小的数(必须每个长度为i的子段都出现)
思路
首先观察题目发现\(1\leq a[i]\leq n\leq 3*10^5\),也就是说我们可以通过枚举去解决这个问题,让我们考虑枚举每两个相同数字的之间的最大距离,也就是说这个距离范围内可以包含至少一个这个数。
\(ans[i]\)长度为\(i\)的最小的数字为\(ans[i]\)。
需要特殊考虑的情况是头和尾,因为有的数字可能存中间开始出现。
\(vector<int>g[maxn]\)通过枚举每个数的下标间距离实现\(O(n)\)的计算。
需要特别注意的是如果长度小的是\(ans[i]\)那么大于这个长度的也可以能是\(ans[i]\),比如说\(ans[2]=4\),\(ans[3]=5\),那么\(ans[3]=4\)也是可以的。
#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int maxn=3e5+10;
int ans[maxn],a[maxn];
vector<int>g[maxn];
void solve(){
int n;cin>>n;
for(int i=1;i<=n;++i){
g[i].clear();ans[i]=1e9;
}
for(int i=1;i<=n;++i){
cin>>a[i];
g[a[i]].push_back(i);
}
for(int i=1;i<=n;++i){
int sz=g[i].size();
if(sz){
int mx=0;
for(int j=1;j<sz;++j){
mx=max(mx,g[i][j]-g[i][j-1]);
}
mx=max(mx,g[i].front());
mx=max(mx,n-g[i].back()+1);
ans[mx]=min(ans[mx],i);
}
}
for(int i=2;i<=n;++i){
ans[i]=min(ans[i],ans[i-1]);
}
for(int i=1;i<=n;++i){
if(ans[i]!=1e9)cout<<ans[i]<<" ";
else cout<<"-1 ";
}
cout<<endl;
}
signed main(){
int t;
cin>>t;
while(t--){
solve();
}
}

浙公网安备 33010602011771号