P14825 纯纯暴 个人题解
题目大意
给定一个正整数序列 \(a\),可以对于其任意满足 \(2\le i<\left| a \right|\) 且 \(a_{i-1}\le a_i\le a_{i+1}\) 的下标 \(i\),然后删除 \(a_i\),一直进行此操作至无法操作,求此时序列的长度。
Solution
对于删除操作我们可以把他理解为找这段序列中非严格上升子序列,因为每删除一个数,他后面那个数就会往前移,并且要删除一个数必须保证他前面后面非严格递增,那么这段非严格上升子序列中能删除的个数即为这段子序列的长度减二。我们可以用一个 \(last\) 变量表示前一个数,如果这个数大于等于 \(last\),那么长度加一;否则能删除的个数即为这段长度减一(因为这里长度没有加第一个数,所以只需要减一),并把长度重新赋值为 \(0\),然后如果最后长度不为零,再把这段长度的贡献加入就行,答案即为总长度减去能删除的个数。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int n=read(),a[N],ans=0;
signed main(){
for(int i=1;i<=n;i++)
a[i]=read();
int last=a[1],cnt=0;
//last为上一个数,cnt为这段非严格上升子序列的长度
for(int i=2;i<=n;i++){
if(a[i]<last)//如果小于,统计这段的贡献,为了避免出现-1的情况,这里与0取max
ans+=max(0ll,cnt-1),cnt=0;//把长度清零
else//否则长度+1
cnt++;
last=a[i];
}
if(cnt!=0)//如果最后长度不为空,加入这段的贡献
ans+=cnt-1;
printf("%lld",n-ans);//最后答案为总长度-能删去的个数
return 0;
}

浙公网安备 33010602011771号