Buy Low, Buy Lower

给出一个长度为N序列\(\{a_i\}\),询问最长的严格下降子序列,以及这样的序列的个数,\(1 <= N <= 5000\)。

显然我们可以很轻易地求出严格下降子序列,思维的过程应该是从熟悉走向不熟悉,从自然走向不自然,因此还是照搬老套路,设\(f_i\)表示以i结尾的最长严格下降子序列的长度,\(g_i\)表示这样的序列的方案数。

接着我们发现,方案之所以不能照搬转移,关键在于结尾有多个相同的数,它们的方案发生了叠加,再仔细研究,你会发现,最靠近i的数必然包括了所有的方案,于是我们只要桶排就可以做到寻找最近的数。

注意到数字可能很大,于是可以事先离散化,而且此题需要打高精度,然后就可以做了。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define Size 5010
using namespace std;
struct lll{
int num[75];
il lll(){clear();}
il void clear(){
memset(num,0,sizeof(num));
num[0]|=true;
}
il void read(){
string s;cin>>s,num[0]=s.size();
for(ri int i(1);i<=num[0];++i)
num[i]=s[num[0]-i]-48;
}
il void print(){
for(int i(num[0]);i;--i)
putchar(num[i]+48);
putchar('\n');
}
il bool operator!(){
return num[0]==1&&num[1]==0;
}
il void operator=(string s){
num[0]=s.size();
for(ri int i(1);i<=num[0];++i)
num[i]=s[num[0]-i]-48;
}
il lll operator+(lll x){
lll y;y.clear();ri int i;
for(i=1;i<=num[0]||i<=x.num[0];++i){
y.num[i]+=num[i]+x.num[i];
if(y.num[i]>9)y.num[i]-=10,++y.num[i+1];
}if(i>1&&!y.num[i])--i;return y.num[0]=i,y;
}
il void operator+=(lll x){
ri int i;
for(i=1;i<=num[0]||i<=x.num[0];++i){
num[i]+=x.num[i];if(num[i]>9)num[i]-=10,++num[i+1];
}while(i>1&&!num[i])--i;num[0]=i;
}
}fp[Size];
struct lsh{
int a[Size],b[Size],n;
il int look(int x){
return b[x];
}
il void prepare(int x,int ar[]){
n=x;
for(ri int i(1);i<=n;++i)
a[i]=ar[i];sort(a+1,a+n+1);
for(ri int i(1);i<=n;++i)
b[i]=dfs(ar[i]);
}
il int dfs(int x){
int l(1),r(n),mid;
while(l<=r){
mid=l+r>>1;
if(a[mid]<x)l=mid+1;
else r=mid-1;
}return l;
}
}L;
bool b[Size];
int a[Size],dp[Size];
il void read(int&);
int main(){
int n;read(n);
for(int i(1);i<=n;++i)read(a[i]);
L.prepare(n,a),a[++n]=-1;
for(int i(1),j;i<=n;++i){
memset(b,0,sizeof(b));
for(j=i-1;j;--j)
if(a[j]>a[i]){
if(dp[j]>dp[i])
dp[i]=dp[j],fp[i]=fp[j],
b[L.look(j)]|=true;
else if(dp[i]==dp[j]&&!b[L.look(j)])
fp[i]+=fp[j],b[L.look(j)]|=true;
}
++dp[i];if(!fp[i])fp[i]="1";
}printf("%d ",dp[n]-1),fp[n].print();
return 0;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

Buy Low, Buy Lower的更多相关文章

  1. USACO Section 4.3 Buy low,Buy lower(LIS)

    第一眼看到题目,感觉水水的,不就是最长下降子序列嘛!然后写……就呵呵了..要判重,还要高精度……判重我是在计算中加入各种判断.这道题比看上去麻烦一点,但其实还好吧.. #include<cstd ...

  2. POJ-1952 BUY LOW, BUY LOWER(线性DP)

    BUY LOW, BUY LOWER Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9244 Accepted: 3226 De ...

  3. USACO 4.3 Buy Low, Buy Lower

    Buy Low, Buy Lower The advice to "buy low" is half the formula to success in the stock mar ...

  4. poj1952 BUY LOW, BUY LOWER【线性DP】【输出方案数】

    BUY LOW, BUY LOWER Time Limit: 1000MS   Memory Limit: 30000K Total Submissions:11148   Accepted: 392 ...

  5. 洛谷P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower

    P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower 题目描述 “逢低吸纳”是炒股的一条成功秘诀.如果你想成为一个成功的投资者,就要遵守这条秘诀: "逢低吸纳,越低越 ...

  6. POJ 1952 BUY LOW, BUY LOWER 动态规划题解

    Description The advice to "buy low" is half the formula to success in the bovine stock mar ...

  7. [POJ1952]BUY LOW, BUY LOWER

    题目描述 Description The advice to "buy low" is half the formula to success in the bovine stoc ...

  8. BUY LOW, BUY LOWER_最长下降子序列

    Description The advice to "buy low" is half the formula to success in the bovine stock mar ...

  9. POJ 1952 BUY LOW, BUY LOWER

    $dp$. 一开始想了一个$dp$做法,$dp[i][j]$表示前$i$个数字,下降序列长度为$j$的方案数为$dp[i][j]$,这样做需要先离散化然后用树状数组优化,空间复杂度为${n^2}$,时 ...

随机推荐

  1. 【CF886E】Maximum Element

    题目 考虑正难则反,答案即为\(n!-\text{返回值为n的排列数}\) 一个排列的返回值为\(n\),当且仅当在\(n\)出现之前没有一个数后面有连续\(k\)个小于它的数 设\(f_i\)表示\ ...

  2. Samcompu Loves Water

    题目背景 Samcompu拥有大量的"水"资源!! 题目描述 Samcompu需要制定一个水计划.这个计划的主要目的就是为了避开老师监视的时间来水. 老师在中途会离开机房T次,第i ...

  3. 第十篇 scrapy item loader机制

    在我们执行scrapy爬取字段中,会有大量的和下面的代码,当要爬取的网站多了,要维护起来很麻烦,为解决这类问题,我们可以根据scrapy提供的loader机制 def parse_detail(sel ...

  4. layui 封装自定义模块

    转自:https://lianghongbo.cn/blog/430585105a35948c layui是国人开发的一款非常简洁的UI框架,使用了模块化加载方式,因此在使用过程中我们难免需要添加自己 ...

  5. linux秘钥登录

    秘钥登录首先要了解四个文件: 公钥文件,私钥文件, authorized_keys, 还有/etc/ssh/sshd_config配置文件. 公钥文件存放在被登陆的机器上, 要将公钥添加进author ...

  6. java常用类——比较器

    Comparable和Comparator接口都是为了对类进行比较,众所周知,诸如Integer,double等基本数据类型,java可以对他们进行比较,而对于类的比较,需要人工定义比较用到的字段比较 ...

  7. C#中反射的基础基础基础

    class Program { static void Main(string[] args) { Type t = typeof(Student);//typeof(类) 取类的类型 并且存储在Ty ...

  8. redis集群报错:(error) MOVED 5798 127.0.0.1:7001

    原因 这种情况一般是因为启动redis-cli时没有设置集群模式所导致. 解决方案 启动时使用-c参数来启动集群模式,命令如下: redis-cli -c -p 7000 测试 127.0.0.1:7 ...

  9. delphi xe10 中使用剪贴板(跨平台)

    VCL 中如何使用剪贴板咱就不说了,FMX 做为一个新的框架,提供了跨平台的剪贴板支持.FMX 对剪贴板的支持来自两个接口: IFMXClipboardService:位于 FMX.Platform. ...

  10. 依赖背包变形(经典)——poj1155

    这个题用优化后的依赖背包做难以实现,所以用常规的泛化物品的和来做即可 每个节点的容量定义为这个节点下的叶子结点个数,dp[u][j]用来表示节点u下选取j个物品的最大收益,最后从m-0查询dp[1][ ...