C. k-Amazing Numbers

    科技2022-08-07  111

    Codeforces Round #673 (Div. 2)

    题意

    给你一个长度为n的数组,让你找到以i为长度的子段中都出现的最小的数(必须每个长度为i的子段都出现)

    思路

    首先观察题目发现 1 ≤ a [ i ] ≤ n ≤ 3 ∗ 1 0 5 1\leq a[i]\leq n\leq 3*10^5 1a[i]n3105,也就是说我们可以通过枚举去解决这个问题,让我们考虑枚举每两个相同数字的之间的最大距离,也就是说这个距离范围内可以包含至少一个这个数。

    a n s [ i ] ans[i] ans[i]长度为 i i i的最小的数字为 a n s [ i ] ans[i] ans[i]

    需要特殊考虑的情况是头和尾,因为有的数字可能存中间开始出现。

    v e c t o r < i n t > g [ m a x n ] vector<int>g[maxn] vector<int>g[maxn]通过枚举每个数的下标间距离实现 O ( n ) O(n) O(n)的计算。

    需要特别注意的是如果长度小的是 a n s [ i ] ans[i] ans[i]那么大于这个长度的也可以能是 a n s [ i ] ans[i] ans[i],比如说 a n s [ 2 ] = 4 ans[2]=4 ans[2]=4, a n s [ 3 ] = 5 ans[3]=5 ans[3]=5,那么 a n s [ 3 ] = 4 ans[3]=4 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(); } }
    Processed: 0.009, SQL: 8