1. 程式人生 > >Codeforce 547B - Mike and Feet

Codeforce 547B - Mike and Feet

題意:給定一個數組,對於這個陣列構造n個長度為1到n的區間,要求最小值最大,輸出構造區間的最小值。

轉換一下題意,可以求每一個數字是多長區間的最小值。
先正著求這個數字的左半邊覆蓋長度,再倒著求右半邊覆蓋長度。

然後用r - l + 1算出區間長度,對於該長度的區間取最大值。

這樣搞很顯然會有許多區間還沒有答案,但是我們可以想到,長的區間都有答案,那短的區間也會有答案,短的區間的答案只會大於等於長的區間。因此可以用長的區間去更新短的區間。

這樣複雜度可能會去到 O (

n ² ) O(n²) 。但是根據上面的結論,即短區間的答案只會大於等於長區間,所以答案序列一定是一個單調遞減的序列,所以我們可以直接從後往前更新最大值。

嗯,字尾自動機經常這麼幹,沒想到用到了這裡。

ac程式碼:

#include<bits/stdc++.h>
using namespace std;

const
int maxn = 2e5 + 5; int n, a[maxn]; int l[maxn], r[maxn]; int ans[maxn]; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } for(int i = 1; i <= n; i++) { l[i] = i; while(a[l[i] - 1] >= a[i]) { l[i] = l[l[i] - 1]; } } for(int i = n; i >=
1; i--) { r[i] = i; while(a[r[i] + 1] >= a[i]) { r[i] = r[r[i] + 1]; } } for(int i = 1; i <= n; i++) { int e = r[i] - l[i] + 1; ans[e] = max(ans[e], a[i]); } for(int i = n - 1; i >= 1; i--) { ans[i] = max(ans[i], ans[i + 1]); } for(int i = 1; i <= n; i++) { printf("%d ", ans[i]); } printf("\n"); return 0; }