hdu 6592 Beauty Of Unimodal Sequence (LIS + 单调栈)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6592
先分别正着反着求一遍 \(LIS\),
可以证明,字典序最小的单峰序列,一定是先找到最左边的峰点,向左单调栈维护每一个长度的最左边的位置,向右贪心
最大字典序同理
维护单调栈时要注意元素大小的单调性
注意输出不能有行末空格
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 300010;
int n, inf;
int a[maxn], b[maxn], f[maxn], g[maxn];
int c[maxn], d[maxn], t[maxn], p[maxn];
int ans1[maxn], ans2[maxn];
int sta[maxn], top;
bool check1(P x, P y){
if(x.first == y.first){
return x.second > y.second;
}
return x.first < y.first;
}
bool check2(P x, P y){
if(x.first == y.first){
return x.second < y.second;
}
return x.first < y.first;
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(scanf("%d", &n) != EOF){
memset(f, 0x3f, sizeof(f));
memset(g, 0x3f, sizeof(g));
inf = f[0];
memset(c, 0, sizeof(c));
memset(d, 0, sizeof(d));
memset(p, 0, sizeof(p));
for(int i = 1 ; i <= n ; ++i) scanf("%d", &a[i]);
for(int i = 1 ; i <= n ; ++i){
int pos = lower_bound(f + 1, f + 1 + n, a[i]) - f;
f[pos] = a[i];
c[i] = pos;
}
for(int i = n ; i >= 1 ; --i){
int pos = lower_bound(g + 1, g + 1 + n, a[i]) - g;
g[pos] = a[i];
d[i] = pos;
}
int sp = 1, bp = n;
int m = c[1] + d[1];
for(int i = 2 ; i <= n ; ++i){
if(c[i] + d[i] > m){
m = c[i] + d[i];
sp = i;
}
}
m = c[n] + d[n];
for(int i = n - 1 ; i >= 1 ; --i){
if(c[i] + d[i] > m) {
m = c[i] + d[i];
bp = i;
}
}
top = 0; p[c[sp]] = a[sp];
for(int i = sp - 1 ; i >= 1 ; --i){
if(a[i] >= p[c[i] + 1]) continue;
while(c[sta[top]] <= c[i] && top >= 1) --top;
sta[++top] = i;
p[c[i]] = a[i];
}
int num = 0;
for(int i = top ; i >= 1 ; --i){
ans1[++num] = sta[i];
}
ans1[++num] = sp;
int cnt = 0;
int las = sp;
for(int i = sp + 1 ; i <= n ; ++i){
if(a[i] >= a[las]) continue;
if(d[i] == d[las] - 1){
t[++cnt] = i;
las = i;
}
}
for(int i = 1 ; i <= cnt ; ++i){
ans1[++num] = t[i];
}
for(int i = 1 ; i <= num ; ++i){
printf("%d", ans1[i]);
if(i != num) printf(" ");
}
printf("\n");
memset(p, 0, sizeof(p));
p[d[bp]] = a[bp];
top = 0;
for(int i = bp + 1 ; i <= n ; ++i){
if(a[i] >= p[d[i] + 1]) continue;
while(d[sta[top]] <= d[i] && top >= 1) --top;
sta[++top] = i;
p[d[i]] = a[i];
}
cnt = 0;
las = bp;
for(int i = bp - 1 ; i >= 1 ; --i){
if(a[i] >= a[las]) continue;
if(c[i] == c[las] - 1){
t[++cnt] = i;
las = i;
}
}
num = 0;
for(int i = cnt ; i >= 1 ; --i) {
ans2[++num] = t[i];
}
ans2[++num] = bp;
for(int i = 1 ; i <= top ; ++i){
ans2[++num] = sta[i];
}
for(int i = 1 ; i <= num ; ++i){
printf("%d", ans2[i]);
if(i != num) printf(" ");
}
printf("\n");
}
return 0;
}