HDU4991 Ordered Subsequence (树状数组优化DP)
2024-09-18 05:37:55
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 }
最新文章
- Python成长笔记 - 基础篇 (九)
- 关于alpha透明度
- Swift3.0语言教程字符串转换为数字值
- google快捷键,通过浏览器本身来查看
- windows7下使用telnet
- THD 变量存入threads中
- oracle 删除表、数据
- 阅读《RobHess的SIFT源码分析:综述》笔记2
- actionscript sendToURL请求url,传递http_referer分浏览器统计
- Google Code Jam Round 1A 2015 Problem B. Haircut 二分
- gitflow 在windows下的安装方法
- fastcgi_param 详解
- Gradle 1.12用户指南翻译——第五十三章. 签名插件
- vue 渲染后更新数据
- springboot整合多数据源及事物
- GPU并行的基础知识
- canvas+js+面向对象的圆形封装
- EF Core 2.1 支持数据库一对一关系
- poj1475 Pushing Boxes(BFS)
- [洛谷P3833][SHOI2012]魔法树