见标题链接.
既然有两种情况, 就一个个解决吧, 先第二种情况,
设 表示前 个能够选择出的最多花盆, 表示位置作为 低点, 表示位置作为 高点.
初值 .
则
先提交一下 暴力, 检验正确性, 结果 爆炸.
原来题目要求的偶数位为 最低点/最高点 可以当做选出最后一个盆栽啊!
于是
初值 ,
也不用一个一个情况讨论了, 因为相当于求的是 最长波浪 了.
改了之后就有 了, Luogu跑的真快 .
使用权值线段树优化为 即可.
#include<bits/stdc++.h>
#define reg register
const int maxn = 100005;
int N;
int Ans;
int H[maxn];
int F[maxn][2];
struct Node{ int l, r, max_v; } T[2][(int)(4e6)+5];
void Build(int k, int l, int r){
T[0][k].l = T[1][k].l = l, T[0][k].r = T[1][k].r = r;
if(l == r){
T[1][k].max_v = T[0][k].max_v = 0;
return ;
}
int mid = l+r >> 1;
Build(k<<1, l, mid), Build(k<<1|1, mid+1, r);
T[0][k].max_v = T[1][k].max_v = 0;
}
void Modify(int k, int pos, int val, int opt){
int l = T[opt][k].l, r = T[opt][k].r;
if(l == r){ T[opt][k].max_v = val; return ; }
int mid = l+r >> 1;
if(pos <= mid) Modify(k<<1, pos, val, opt);
else Modify(k<<1|1, pos, val, opt);
T[opt][k].max_v = std::max(T[opt][k<<1].max_v, T[opt][k<<1|1].max_v);
}
int Query(int k, int Ql, int Qr, int opt){
if(Ql > Qr) return 0;
int l = T[opt][k].l, r = T[opt][k].r;
if(Ql <= l && r <= Qr) return T[opt][k].max_v;
int mid = l+r >> 1;
if(Qr <= mid) return Query(k<<1, Ql, Qr, opt);
else if(Ql >= mid+1) return Query(k<<1|1, Ql, Qr, opt);
return std::max(Query(k<<1, Ql, Qr, opt), Query(k<<1|1, Ql, Qr, opt));
}
int main(){
scanf("%d", &N);
int Lim = 1;
for(reg int i = 1; i <= N; i ++) scanf("%d", &H[i]), Lim = std::max(H[i], Lim);
Build(1, 0, Lim);
for(reg int i = 1; i <= N; i ++){
F[i][0] = Query(1, 0, H[i]-1, 1) + 1;
F[i][1] = Query(1, H[i]+1, Lim, 0) + 1;
Modify(1, H[i], F[i][0], 0);
Modify(1, H[i], F[i][1], 1);
Ans = std::max(Ans, F[i][1]);
Ans = std::max(Ans, F[i][0]);
}
printf("%d
", Ans);
return 0;
}