HDU4991 Ordered Subsequence (树状数组优化DP)
dp[i][j]表示以a[i]结尾的长度为j的上升子序列个数。
方程:dp[i][j]=sum(dp[k][j-1]),a[k]<a[i],1<=k<i。
求解目标:sum(dp[k][m]),1<=k<=n。
三层循环枚举的话要超时,观察式子,相当于是统计前缀和,这启示我们可以用到树状数组来优化,复杂度mnlogn。
值域较大,要使用离散化。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mod 123456789 5 typedef long long ll; 6 using namespace std; 7 #define N 10005 8 9 ll a[N],b[N]; 10 ll dp[N][105]; 11 int n,m,len; 12 13 int lowbit(int x){ 14 return x&(-x); 15 } 16 17 void add(int i,int j,ll val){ 18 while(i<=len){ 19 dp[i][j]=(dp[i][j]+val)%mod; 20 i+=lowbit(i); 21 } 22 } 23 24 ll query(int i,int j){ 25 ll res=0; 26 while(i){ 27 res=(res+dp[i][j])%mod; 28 i-=lowbit(i); 29 } 30 return res; 31 } 32 33 34 35 int main(){ 36 while(~scanf("%d%d",&n,&m)){ 37 for(int i=1;i<=n;i++){ 38 scanf("%lld",&a[i]); 39 b[i]=a[i]; 40 } 41 memset(dp,0,sizeof(dp)); 42 sort(b+1,b+n+1); 43 len=unique(b+1,b+n+1)-b-1; 44 for(int i=1;i<=n;i++){ 45 int pos=lower_bound(b+1,b+len+1,a[i])-b; 46 add(pos,1,1); 47 for(int j=2;j<=m;j++){ 48 int sum=query(pos-1,j-1); 49 add(pos,j,sum); 50 } 51 } 52 printf("%lld\n",query(len,m)); 53 } 54 return 0; 55 }
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?