O(n^2) LIS 附带方案数
思路:
b [ i ] :以第i天为结尾,最大购买次数
f [ i ] :到第i天,最大购买次数
ok [ a [ i ] ]:在与 a [ i ] 价格相同的情况下,该价格是否为最优
y:当前 i ,循环到 j 时的最大 b [ ]
转移方程:b [ i ] = max{b [ j ] }+1,1<=j<=i-1
f [ i ]=f [ j ],b [ j ] > y
f [ i ]+=f [ j ] ,b [ j ] == y && ! flag [ a [ i ] ]
PS:1.flag [ ]需要以价格为下标以避免出现价格队列相同,而方案数累加的情况
2.flag [ ]须定义为布尔数组,开2^16,大了或者开int会T,小了会WA
附代码:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define ll long long 5 const int N=5010; 6 ll f[N],b[N],a[N],y; 7 bool flag[65537]; 8 int main(){ 9 int n; 10 scanf("%d",&n); 11 for (int i=1;i<=n;i++) 12 scanf("%lld",&a[i]); 13 f[1]=b[1]=1; 14 a[0]=0; 15 for (int i=2;i<=n+1;i++){ 16 y=0; 17 f[i]=1; 18 for (int j=i-1;j>=1;j--) 19 if (a[i]<a[j]){ 20 if (b[j]>y){ 21 memset(flag,0,sizeof(flag)); 22 flag[a[j]]=1; 23 y=b[j]; 24 f[i]=f[j]; 25 } 26 else if (b[j]==y&&!flag[a[j]]){ 27 f[i]+=f[j]; 28 flag[a[j]]=1; 29 } 30 } 31 b[i]=y+1; 32 } 33 printf("%lld %lld",b[n+1]-1,f[n+1]); 34 return 0; 35 }
浙公网安备 33010602011771号