题解 【POJ1952】 BUY LOW, BUY LOWER
2024-08-30 21:51:11
题目意思:
给你一个长度为\(n\)(\(1<=n<=5000\))的序列,并求出最长下降子序列的长度及个数,
并且,如果两个序列中元素的权值完全相同,那么即使它们的位置不一样,也只算一种情况.
解析
长度应该都能轻松求出来吧.
然而,情况数却有点难求啊..
其实主要是去重(要不然用计数\(DP\)也能过)...
但仔细想想,
首先,我们设\(f[i]\)为以\(i\)结尾的最长下降子序列的长度,
\(s[i]\)为以\(i\)结尾的最长上升子序列的个数.
那么对于两个权值相同的元素\(i\),\(j\),且\(i<j\),\(f[i]=f[j]\)(若不等于则不可能造成影响),
那么,以\(i\)结尾的序列,都能用\(j\)替换\(i\),
即\(s[i]\)的情况都会计算到\(s[j]\)中,
所以,在计算\(j\)的时候,将所有\(a[i](\)即权值\()=a[j]\),且\(f[i]=f[j]\)的\(s[i]\)都减掉就行了,
最后,上代码吧:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
}
int n,a[100001],ans,ret;
int s[100001],f[100001];
int main(){
n=read();
s[0]=1;
for(int i=n;i;i--) a[i]=read();//倒过来也就变成了最长上升子序列,仅仅是个人习惯
for(int i=1;i<=n;i++){
int len=0;
for(int j=1;j<i;j++){
if(a[i]>a[j]) len=max(len,f[j]);
}
f[i]=len+1;
for(int j=0;j<i;j++){
if(f[j]==len&&a[j]<a[i]) s[i]+=s[j];
}
for(int j=0;j<i;j++) if(a[i]==a[j]&&f[j]==f[i]) s[i]-=s[j];//去重
}
for(int i=1;i<=n;i++) ans=max(ans,f[i]);//寻找最长子序列
for(int i=1;i<=n;i++) if(f[i]==ans) ret+=s[i];//统计答案
printf("%d %d\n",ans,ret);
return 0;
}
最新文章
- swift uiview弹出动画
- C语言中,宏和全局变量的区别是什么?
- Web 在线文件管理器学习笔记与总结(5)修改文件内容
- for name in loop Shell
- 实现推送功能APP端需要完成的工作
- (转)MySQL Workbench的使用教程 (初级入门版)
- 《C#并行编程高级教程》第5章 协调数据结构 笔记
- RxJava 与 Retrofit 结合的最佳实践
- Unity3D-第一视角射击游戏
- MacOS下使用VMware5 破解 安装win7 ISO 激活
- Java的类C结构体的实现,以及对类的某一属性进行排序
- 【Linux基础】Linux命令date 日期时间
- python web编程之网络基础
- Daily record-September
- php简单使用shmop函数创建共享内存减少服务器负载
- mathematica入门学习记录:
- PostgreSQL索引页
- error ";OPatch cannot find a valid oraInst.loc file to locate Central Inventory
- 如何让邮件营销平台成为EDM神器?
- spring4-2-bean配置-10-通过FactoryBean配置bean