BUY LOW, BUY LOWER, POJ

一开始疯狂WA,后来用别人题解代码debug发现
2
1 1
这组数据应该输出1,而我输出0,原来是ans初始化错了。。。。

解析:
我去重的思想是,如果a [ i ] == a [ j ] (j<i) && dp [ i ] == dp [j ] ,那么说明就存在重复序列了,为了避免之后算重复,则有:

(f为计数数组,储存的是长度为dp[ i ]且以a [ i ] 结尾的 对应的不重复序列数
f [ i ] -= f [ j ](好像f [ i ] = 0也是一个道理),这样后面更新时,就只会加一个 f [ j ], 不会重复,因为之前的重复的被减掉了;

而如果 dp [ i ] 被更新了,则 f [ i ] = f [ j ] (dp [ i ] = dp [ j ] + 1 时),因为最长长度增加了,f [ i ] 就重置了(正如前面 f 数组的定义);

a[ i ] < a [ j ] 的情况就照常计数。

AC代码

#include<algorithm>
#include<cctype>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=5e3+5;
LL f[N],dp[N],a[N];
int main()
{
    int n;
    while(scanf("%lld",&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i] );

        LL ans1=1,ans2=1;///初始化
        dp[1]=f[1]=1;
        for(int i=2;i<=n;i++)
        {
            dp[i]=f[i]=1;
            for(int j=1;j<i;j++)
            {
                if(a[i]<a[j])
                {
                    if(dp[i]<dp[j]+1)///重置
                    {
                        dp[i]=dp[j]+1;
                        f[i]=f[j];
                    }
                    else if(dp[i]==dp[j]+1) ///计数
                        f[i]+=f[j];
                }
                else if(a[i]==a[j]&&dp[i]==dp[j])///去重
                    f[i]-=f[j];
            }
            ///算答案
            if(ans1<dp[i])///重置答案
            {
                ans1=dp[i];
                ans2=f[i];
            }
            else if(ans1==dp[i])///计数
                ans2+=f[i];
        }

        printf("%lld %lld
",ans1,ans2);

    }
    return 0;
}

如果有什么没有明白的,可以模拟一下代码运行,或者再下面提问也可以的。

原文地址:https://www.cnblogs.com/DeepJay/p/12025211.html