题目要求是“它们构成的价格队列不一样”,那么我准备拿一个数组存下这个最长下降子序列,但是这不现实,检查是否匹配是在最坏的情况下可能达到Θ(N^3)Θ(N
3
)。
于是有了现在的解法,让我来简单证明说明一下
在dpdp过程中,ff数组存的是最长下降子序列的长度,ff数组的下标ii是以ii结尾的意思,所以最长下降子序列(除了最后一位外)的数据已经丢失,因此不能在方案数相加时再判断是否能加。
我们从头来看,
如果一个数列的第一个数与另一个数列的第一个数相同,那么现在可以判断它们相等,即可以把其中一个删掉(在代码中的处理是t[i]=0t[i]=0)。当不同的数接在它的后面时,又可以将它们判断为两个数列,这是不互相影响的。因为两个数列都可以由这个相等的数列转移而来
如果一个数列的第一个数与另一个数列的第一个数不同,那么它们不等,且无论后面添加什么,都不相等,即不删去,则按照普通的判断继续做。
由上面的两点,我们已经把重复的删掉,这样可以防止重复计数。
//My AC Code:
#include <cstdio>
using namespace std;
int n,mxx;
int f[5005],w[5005],nn[5005];
int max(int a,int b){return a>b?a:b;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&nn[i]);
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++)
if(nn[j]>nn[i])f[i]=max(f[i],f[j]+1);
if(f[i]==0)f[i]=1;//如果当前的数是目前为止最大的,则最长下降子序列是自己
mxx=max(mxx,f[i]);//在f数组更新完毕后,存下最长下降子序列的长度
for(int k=1;k<i;k++)
if(f[i]==f[k]&&nn[i]==nn[k])//如果前i 和 前k 的最长下降序列长度 一样且 i位置和k位置的数一样 则舍弃前面那个数 t[j]=0
w[k]=0;
else if(f[i]==f[k]+1&&nn[k]>nn[i])w[i]+=w[k];//如果可以接上前面的数列,就继承其方案数
if(!w[i])w[i]=1;////如果当前的数是目前为止最大的,则是初始方案
}
int ans=0;//ans用来计算 最长下降子序列长度为mxx ,以不同数结尾的方案
for(int i=1;i<=n;i++)
if(f[i]==mxx)ans+=w[i];
printf("%d %d",mxx,ans);
return 0;
}