D
e
s
c
r
i
p
t
i
o
n
\mathcal{Description}
Description
见标题链接.
最
初
想
法
最初想法
最初想法
既然有两种情况, 就一个个解决吧, 先第二种情况,
设
F
[
i
,
0
/
1
]
F[i,0/1]
F[i,0/1] 表示前
i
i
i 个能够选择出的最多花盆,
0
0
0 表示
i
i
i位置作为 低点,
1
1
1 表示
i
i
i位置作为 高点.
初值
F
[
i
,
1
]
=
1
,
F
[
i
,
0
]
=
0
F[i,1]=1,F[i,0]=0
F[i,1]=1,F[i,0]=0 .
H [ j ] > H [ i ] : F [ i , 0 ] = m a x ( F [ j , 1 ] + 1 ) H [ j ] < H [ i ] : F [ i , 1 ] = m a x ( F [ j , 0 ] + 1 ) H[j]>H[i]:\ \ F[i,0]=max(F[j,1]+1) \\ H[j]<H[i]:\ \ F[i,1]=max(F[j,0]+1) H[j]>H[i]: F[i,0]=max(F[j,1]+1)H[j]<H[i]: F[i,1]=max(F[j,0]+1)
则 A n s = m a x i ∈ [ 1 , N ] ( F [ i , 1 ] ) Ans=max_{i∈[1,N]}(F[i,1]) Ans=maxi∈[1,N](F[i,1])
先提交一下 O ( N 2 ) O(N^2) O(N2) 暴力, 检验正确性, 结果 40 p t s 40pts 40pts 爆炸.
原来题目要求的偶数位为 最低点/最高点 可以当做选出最后一个盆栽啊!
于是
初值
F
[
i
,
1
]
=
F
[
i
,
0
]
=
1
F[i,1]=F[i,0]=1
F[i,1]=F[i,0]=1,
A
n
s
=
m
a
x
i
∈
[
1
,
N
]
(
F
[
i
,
1
]
,
F
[
i
,
0
]
)
Ans=max_{i∈[1,N]}(F[i,1],F[i,0])
Ans=maxi∈[1,N](F[i,1],F[i,0])
也不用一个一个情况讨论了, 因为相当于求的是 最长波浪 了.
改了之后就有
80
p
t
s
80pts
80pts 了, Luogu跑的真快 .
正 解 部 分 正解部分 正解部分
使用权值线段树优化为 O ( N l o g N ) O(NlogN) O(NlogN) 即可.
#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\n", Ans);
return 0;
}