Luogu P1108 低价购买 DP

第一问求最长下降子序列,不提;

第二问:借鉴了最短路的方法???

我们求出来了每个位置的最长下降子序列的长度,那么刻意这样这样转移

if f[i]==f[j]+1&&a[i]<a[j](i>j) 这代表f[i]可以由f[j]转移过来,所以 f[i]+=f[j]

但是会重复,所以当f[i]==f[j]&&a[i]==a[j]  时,说明f[j]中已经包括了f[i]中的所有转移,所以c[i]=0;

初值 当f[i]==1时,c[i]=1;

#include<iostream>
#include<cstdio>
#include<algorithm>
#define max(a,b) a>b?a:b
#define R register int 
using namespace std;
const int N=5010;
int n;
int a[N],f[N],c[N];
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=(ret<<3)+(ret<<1)+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
signed main() {
    n=g();for(R i=1;i<=n;i++) a[i]=g();
    long long ans1=0,ans2=0;
    for(R i=1;i<=n;i++) {
        f[i]=1; 
        for(R j=1;j<i;j++) if(a[i]<a[j]) f[i]=max(f[i],f[j]+1);
        ans1=max(ans1,f[i]);
    }
    for(R i=1;i<=n;i++) {
        if(f[i]==1) c[i]=1;
        for(R j=1;j<i;j++) 
            if(f[i]==f[j]+1&&a[i]<a[j]) c[i]+=c[j];
            else if(f[i]==f[j]&&a[i]==a[j]) c[i]=0;
        if(f[i]==ans1) ans2+=c[i];
    }
    printf("%lld %lld\n",ans1,ans2);
}

2019.04.28

posted @ 2019-04-28 11:58  LuitaryiJack  阅读(114)  评论(0编辑  收藏  举报