[Noip模拟题]Seq
Posted akura
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Noip模拟题]Seq相关的知识,希望对你有一定的参考价值。
题目描述
由于hyf长得实在是太帅了,英俊潇洒,风流倜傥,人见人爱,花见花开,车见车载。有一群MM排队看hyf。每个MM都有自己独特的风格,由于hyf有着一颗包容的心,所以,什么风格的MM他都喜欢……但是,hyf有一个特别的要求,他不希望总是看到风格得差不多的MM,更加特别的是,如果两个MM风格完全一样,hyf不会有任何意见。现在,hyf希望从去看他的MM中,去掉一些MM,从而使得相邻2个MM的风格值的差(绝对值)不为1。自然地,hyf希望去掉的MM越少越好。
输入格式
第一行一个整数N;
第2~N+1行N个整数,第i个为ci。表示第i个MM的风格值。
N≤1000 0 ≤ ci ≤ 2000
输出格式
一个数,表示最少要去掉的MM数。
要去掉的数最少,也就是求最长的满足条件的序列长度。
类似于LIS的做法,我们可以用dp求解。设dp(i)表示1~i满足条件的最长序列的长度。那么可以得出状态转移方程:
\[ dp[i]=Max_1≤j<i,|a[i]-a[j]|\neq1\dp[j]+1\ \]
目标状态为dp(n)。
时间复杂度为O(N^2)。
然而dp并不是最优解,我们可以进行优化。
显然,只有当a(j)=a(i)-1或者a(j)=a(i)+1两种位置不能够进行转移。所以为了保证有解,我们只需要记三个值即可:1~i-1的dp前三大的值,并再记下其所对应的a数组的值。那么三个值里面至少一个能够对dp(i)进行转移,并且转移过来也是最优值。
时间复杂度为O(N)。
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 2001
#define inf 0x3f3f3f3f
using namespace std;
int n,a1=-inf,a2=-inf,a3=-inf,dp1,dp2,dp3;
inline int read()
register int x(0),f(1); register char c(getchar());
while(c<'0'||'9'<c) if(x=='-') f=-1; c=getchar();
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
inline int Abs(const int &x) return x<0?-x:x;
int main()
n=read();
for(register int i=1;i<=n;i++)
int cur=read(),len;
if(Abs(cur-a3)!=1) len=dp3+1;
if(Abs(cur-a2)!=1) len=dp2+1;
if(Abs(cur-a1)!=1) len=dp1+1;
if(cur==a1) dp1=len;
else if(cur==a2) dp2=len;
else if(cur==a3) dp3=len;
else if(len>dp3) a3=cur,dp3=len;
if(dp1<dp2) swap(dp1,dp2),swap(a1,a2);
if(dp1<dp3) swap(dp1,dp3),swap(a1,a3);
if(dp2<dp3) swap(dp2,dp3),swap(a2,a3);
printf("%d\n",n-dp1);
return 0;
以上是关于[Noip模拟题]Seq的主要内容,如果未能解决你的问题,请参考以下文章
6.19 noip模拟题(题目及解析转自 hzwer 2014-3-15 NOIP模拟赛)