Codeforce 547B - Mike and Feet
阿新 • • 發佈:2018-12-03
題意:給定一個數組,對於這個陣列構造n個長度為1到n的區間,要求最小值最大,輸出構造區間的最小值。
轉換一下題意,可以求每一個數字是多長區間的最小值。
先正著求這個數字的左半邊覆蓋長度,再倒著求右半邊覆蓋長度。
然後用r - l + 1算出區間長度,對於該長度的區間取最大值。
這樣搞很顯然會有許多區間還沒有答案,但是我們可以想到,長的區間都有答案,那短的區間也會有答案,短的區間的答案只會大於等於長的區間。因此可以用長的區間去更新短的區間。
這樣複雜度可能會去到 。但是根據上面的結論,即短區間的答案只會大於等於長區間,所以答案序列一定是一個單調遞減的序列,所以我們可以直接從後往前更新最大值。
嗯,字尾自動機經常這麼幹,沒想到用到了這裡。
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;
}