Codeforces Round #673 (Div. 2)C. k-Amazing Numbers
阿新 • • 發佈:2020-10-04
題意
給你一個長度為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]\)
#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(); } }