A:给出一个序列,问能否找出一些点,使得相邻两个数的最小值组成的序列非递减。
首先考虑最长非递减子序列,每个数之间最多能够插入一个比两侧大的数,超过两个就不合法,可以手推或者脑补一下。因此在选择状态转移的时候如果有多个最大值,要选取下标最小的一个,思考一下,如果dp值相同,下标更小的数一定更大,因为后面有更大的数那么可以从这个数进行转移。所以用线段树维护两个数,第一个为dp值,第二个为该位置的值,用last数组表示上一次这个数出现的位置,如果这段区间内有比两侧的数都大的数,那么答案可以为+2,否则+1。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=5e5+5;
int a[maxn],last[maxn];
struct Seg{
int t[maxn<<2];
int m[maxn<<2];
void build(int p,int l,int r){
if(l==r) {
t[p]=0;
m[p]=l;
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p]=max(t[p<<1],t[p<<1|1]);
if(t[p<<1|1]>=t[p<<1]) m[p]=m[p<<1|1];
else m[p]=m[p<<1];
}
void update(int p,int l,int r,int in,int v){
if(l==r){
t[p]=max(t[p],v);
return;
}
int mid=(l+r)>>1;
if(in<=mid) update(p<<1,l,mid,in,v);
else update(p<<1|1,mid+1,r,in,v);
t[p]=max(t[p<<1],t[p<<1|1]);
if(t[p<<1|1]>=t[p<<1]) m[p]=m[p<<1|1];
else m[p]=m[p<<1];
}
pii query(int p,int l,int r,int ql,int qr){
if(qr<ql) return {
0,0};
if(ql<=l&&qr>=r) return {
t[p],m[p]};
int mid=(l+r)>>1;
pii res={
0,0};
if(ql<&#