poj1952 BUY LOW, BUY LOWER[线性DP(统计不重复LIS方案)]
如题。$N \leqslant 5000$。
感觉自己思路永远都是弯弯绕绕的。。即使会做也会被做繁掉。。果然还是我太菜了。
递减不爽,先倒序输入算了。第一问做个LIS没什么说的。第二问统计个数,考虑什么时候是重复计算的。$g[i]$表示第$i$个数结尾的LIS长度的方案(不重复)。当统计时dp到一个数时显然从前面满足$f_j+1=f_i且A_j<A_i$条件的累加过来,$A_j$不同的时候,自然不会有重复;当有相同的数且f一样时,如果这几种都加入,就重复了。而相同的几个数字显然靠后的方案统计到的更多,所以每次只取最靠右的那个数累加上去即可。实现上,开一个桶,记录vis,结束后再吐出来。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+,M=<<,INF=0x3f3f3f3f;
int f[N],g[N],lis[N],a[N],vis[M],bin[N];
int n,len,ans,tot,cnt; int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n);for(register int i=;i<=n;++i)read(a[n-i+]);
lis[len=]=INF;
for(register int i=;i<=n;++i){
f[i]=lower_bound(lis+,lis+len+,a[i])-lis;
if(f[i]>len)lis[++len]=a[i];else lis[f[i]]=a[i];
MAX(ans,f[i]);
}
for(register int i=;i<=n;++i){
if(f[i]==){g[i]=;continue;}
for(register int j=i-;j;--j)if(!vis[a[j]]&&a[j]<a[i]&&f[j]+==f[i])vis[bin[++tot]=a[j]]=,g[i]+=g[j];
while(tot)vis[bin[tot--]]=;
}
for(register int i=n;i;--i) if(!vis[a[i]]&&f[i]==ans)cnt+=g[i],vis[a[i]]=;
printf("%d %d\n",ans,cnt);
return ;
}
嗯这个是本人极其繁琐的想法。发现自己傻了有没有。。而且数据大的话桶不就挂了吗。。所以依据原来思路,改变对于dp状态的定义。$g[i]$表示第$i$个数结尾的长度为LIS的方案数,且不包括之前所有和自己相同且$len_{LIS}$相同的数的方案。这样每次转移时遇到相同即break。保证取的决策一定来源于上一个相同数和现在这个数之间。具体还是看code吧。。
另外还有一种做法是网络流。。不想写了QwQ。 ←不行,建边都会建炸掉
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+,M=<<,INF=0x3f3f3f3f;
int f[N],g[N],lis[N],a[N];
int n,len,ans,tot,cnt; int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n);for(register int i=;i<=n;++i)read(a[n-i+]);
lis[len=]=INF;
for(register int i=;i<=n;++i){
f[i]=lower_bound(lis+,lis+len+,a[i])-lis;
if(f[i]>len)lis[++len]=a[i];else lis[f[i]]=a[i];
MAX(ans,f[i]);
}
g[]=;
for(register int i=;i<=n;++i){
for(register int j=i-;~j;--j){
if(a[i]==a[j]&&f[i]==f[j])break;
if(f[i]==f[j]+&&a[j]<a[i])g[i]+=g[j];
}
}
for(register int i=;i<=n;++i)if(f[i]==ans)cnt+=g[i];
printf("%d %d\n",ans,cnt);
return ;
}
poj1952 BUY LOW, BUY LOWER[线性DP(统计不重复LIS方案)]的更多相关文章
- poj1952 BUY LOW, BUY LOWER【线性DP】【输出方案数】
BUY LOW, BUY LOWER Time Limit: 1000MS Memory Limit: 30000K Total Submissions:11148 Accepted: 392 ...
- POJ-1952 BUY LOW, BUY LOWER(线性DP)
BUY LOW, BUY LOWER Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9244 Accepted: 3226 De ...
- [POJ1952]BUY LOW, BUY LOWER
题目描述 Description The advice to "buy low" is half the formula to success in the bovine stoc ...
- USACO Section 4.3 Buy low,Buy lower(LIS)
第一眼看到题目,感觉水水的,不就是最长下降子序列嘛!然后写……就呵呵了..要判重,还要高精度……判重我是在计算中加入各种判断.这道题比看上去麻烦一点,但其实还好吧.. #include<cstd ...
- 洛谷P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower
P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower 题目描述 “逢低吸纳”是炒股的一条成功秘诀.如果你想成为一个成功的投资者,就要遵守这条秘诀: "逢低吸纳,越低越 ...
- POJ 1952 BUY LOW, BUY LOWER 动态规划题解
Description The advice to "buy low" is half the formula to success in the bovine stock mar ...
- Buy Low, Buy Lower
Buy Low, Buy Lower 给出一个长度为N序列\(\{a_i\}\),询问最长的严格下降子序列,以及这样的序列的个数,\(1 <= N <= 5000\). 解 显然我们可以很 ...
- 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 ...
- BUY LOW, BUY LOWER_最长下降子序列
Description The advice to "buy low" is half the formula to success in the bovine stock mar ...
随机推荐
- 【学习笔记】adb命令
1.adb connect 连接设备 如:adb connect 127.0.0.1:62001 连接夜神模拟器\adb connect 127.0.0.1:21503 链接逍遥模拟器 adb con ...
- B/S结构-登录页面-测试用例设计
页面描述: 有一个登陆页面, 假如上面有2个textbox, 一个提交按钮 测试需求: 请针对这个页面设计30个以上的testcase 功能测试(Function test) 0. 什么都不输入,点击 ...
- @Conditional注解
根据条件动态创建bean public class TestConditon implements Condition { public boolean matches(ConditionContex ...
- 维特比算法及python实现
先放一张找到的算法流程图: 上图解释: A:状态转移概率矩阵,Aij表示状态i到状态j转换的概率,即P(state=j | state=i).下面代码中以P表示. B:观测矩阵,Bij表示给定状态i, ...
- Springboot 上传报错: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The multi-part request contained parameter data (excluding uploaded files) that exceede
Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The ...
- 蓝鲸-监控 排错思路 - 原理push - bkdata报错 - saas的日志
1.现象和报错 .[10.253.124.21] paas_agent() paas_agent FATAL Exited too quickly (process log may have deta ...
- MFC之MessageBox、AfxMessageBox用法
在软件中我们经常会弹出个小窗口,给一点点提示.这就会用到消息对话框. 在Win32 API程序中只有MessageBox这一种用法. 而在MFC中就有三各方法: 1.调用API中的MessageBox ...
- LeetCode-求最长回文子序列
题目:给定一个字符串,求它的最长回文子串 /*求最长回文子串,以当前字符为中心,向两边同时拓展*/ string longestPalindrome(string s) { int len = s.l ...
- sql server 查询某段日期某段时间内的数据
如我要取8月1号到8月30号之间的早上7点半到晚上八点半这段时间内的数据. SELECT * FROM tableName AS tWHERE t.create_date BETWEEN '2017- ...
- 如何获取字符串中某个具体的数值--通过json.load转化成字典形式获取
r=requests.get('http://httpbin.org/get').text print(r) # print(type(r)) # 如果要获取User-Agent的详细数值,需要做JS ...