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 }
复制代码

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示