首页 > 其他 > 详细

【洛谷1108】低价购买

时间:2020-02-08 17:06:53      阅读:70      评论:0      收藏:0      [点我收藏+]

原题:

技术分享图片

 

 n<=5000

 

第一个子问题是求最长下降子序列的长度,这个大家都会,用一个单调的g数组+二分可以nlogn求

第二个子问题是求本质不同的方案数

其实数据只有5000,可以用n^2来实现第一个子问题,完全没必要局限于nlogn的做法

研究本质相同的方案的特点

a表示输入的价格序列,g[i]和g[j]表示a[i]或a[j]结尾的方案数

如果j>i且a[j]==a[i],那么g[j]一定>=g[i]

因为a[i]结尾的所有序列都可以继承到a[j],而i和j中间可能还给a[j]提供了更多方案

前一部分是本质相同的方案数,因此可以直接无视a[i]而使a[j]给后续状态转移

这个很容易n^2处理,里层循环从右往左枚举,只统计每个价格第一次出现时的方案数

 

代码:

技术分享图片
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int n,a[5100];
 5 int f[5100];
 6 bool u[110000];
 7 long long g[5100];
 8 int main(){
 9     cin>>n;
10     for(int i=1;i<=n;++i)  scanf("%d",&a[i]);
11     for(int i=1;i<=n+1;++i){
12         f[i]=1;
13         for(int j=i-1;j>=1;--j)if(a[j]>a[i])
14             f[i]=max(f[i],f[j]+1);
15         for(int j=i-1;j>=1;--j)if(a[j]>a[i] && f[j]==f[i]-1 && !u[a[j]]){
16             u[a[j]]=true;
17             g[i]+=g[j];
18         }
19         if(f[i]==1)  g[i]=1;
20         for(int j=i-1;j>=1;--j)if(u[a[j]])  u[a[j]]=false;
21     }
22     cout<<f[n+1]-1<<" "<<g[n+1]<<endl;
23     return 0;
24 }
View Code

 

【洛谷1108】低价购买

原文:https://www.cnblogs.com/cdcq/p/12283499.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!