1. 程式人生 > 實用技巧 >Codeforces Round #673 (Div. 2)C. k-Amazing Numbers

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();
    }
}