HDU2227Find the nondecreasing subsequences(树状数组+DP)
题目大意就是说帮你给出一个序列a,让你求出它的非递减序列有多少个。
设dp[i]表示以a[i]结尾的非递减子序列的个数,由题意我们可以写出状态转移方程:
dp[i] = sum{dp[j] | 1<=j<i && a[j] <= a[i]} + 1.
这样一来这里面所有的dp[]值的和就是最后的结果。
但是这个状态转移方程很明显复杂度是O(n^2),但是n可以达到100000,很明显会超时。既然是求前导和,很明显我们就应该可以想到用树状数组(虽然我怎么也不可能想到==!),这样一来那么复杂度就可以降到O(nlogn)。
那么怎么求前导和呢??也并不是所有的dp[j](1<=j<i)都要被加进去啊,只有满足a[j]<=a[i]时dp值才可以被计算在内。。。
解决办法就是先将原数组复制一份,然后排序,然后再按照原顺序找出每一个数的排序后的所在位置,然后计算这个位置的dp[]值,可以通过一例看出他的正确性:
原数组: 8 5 3 4 1
排序后: 1 3 4 5 8
可以看出原数组的每一个数对应到排序后的下标就是:5 4 2 3 1
没有计算前,树状数组里的值全为0,然后
1、找到8的位置,并计算以‘8’结尾的dp[]的值,也就是计算‘8’在排序后所在位置5的值, 计算dp[5] = 0 + 1 = 1
2、然后找到‘5’在排序后的位置4,由于‘8’>‘5’,所以以‘5’结尾的dp值应该也是1,正好排序后‘5’在第4个,在‘8’前面,自然dp[4]计算出来还是1
3、同理,‘3’出现在第二个,dp[2] = 1
4、然后到‘4’,他在排序后出现在第3 个,而原数组中‘4’之前有一个数‘3’,所以计算出来以‘4’结尾的dp[]值应该就是以‘3’结尾的dp值+1等于2,而我们看排序后4出现在第3个,而第3个之前又正好有一个dp[2]=1已经被计算出来了,这样dp值的前导和就是1,从而dp[3] = dp[2] + 1 = 2.
5、最后dp[1] = 1.所以最后结果就是1+1+1+2+1 = 6
其实上面的排序找到下标就是为了保证每个数计算出来的值都是满足a[j] < a[i]时,所计算出来的dp值。这也就是原题的解。
而要实现找到原数组在排序后的位置,我们只需要二分查找就可以了,又因为原数组可能会有相同的数,为了找到的是同一个标号,所以需要二分查找下限(或者上限)。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define mem(a) memset(a,0,sizeof(a))
#define mod 1000000007
#define MAXN 100010 int num[MAXN], d[MAXN], N, DP[MAXN]; int lowbit(int x)
{
return x & -x;
} int getSum(int k)
{
int ans = ;
while(k>=)
{
ans = (ans + DP[k]) % mod;
k -= lowbit(k);
}
return ans;
} void edit(int k,int val)
{
while(k<=N)
{
DP[k] = (DP[k] + val) % mod;
k += lowbit(k);
}
} int bsearch(int num)
{
int x = , y = N+, mid;
while(y > x )
{
mid = (x+y)/;
if(d[mid] == num && d[mid-]<num) return mid;
if(d[mid] >= num) y = mid;
else x = mid+;
}
return mid;
} int main()
{
while(~scanf("%d", &N))
{
mem(DP);
mem(d); mem(num);
for(int i = ; i <= N; i ++)
{
scanf("%d", &num[i]);
d[i] = num[i];
}
sort(d+, d+N+);
for(int i=;i<=N;i++)
{
int id = bsearch(num[i]);
edit(id, getSum(id)+);
}
printf("%d\n", getSum(N));
}
return ;
}
HDU2227Find the nondecreasing subsequences(树状数组+DP)的更多相关文章
- Codeforces 597C. Subsequences (树状数组+dp)
题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长 ...
- CodeForces - 314C Sereja and Subsequences (树状数组+dp)
Sereja has a sequence that consists of n positive integers, a1, a2, ..., an. First Sereja took a pie ...
- hdu 2227(树状数组+dp)
Find the nondecreasing subsequences Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/3 ...
- hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)
Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- hdu 4991(树状数组+DP)
Ordered Subsequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- codeforces 597C (树状数组+DP)
题目链接:http://codeforces.com/contest/597/problem/C 思路:dp[i][j]表示长度为i,以j结尾的上升子序列,则有dp[i][j]= ∑dp[i-1][k ...
- hdu 4622 Reincarnation trie树+树状数组/dp
题意:给你一个字符串和m个询问,问你l,r这个区间内出现过多少字串. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 网上也有用后缀数组搞得. 思路 ...
- HDU 6348 序列计数 (树状数组 + DP)
序列计数 Time Limit: 4500/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Subm ...
- [Codeforces261D]Maxim and Increasing Subsequence——树状数组+DP
题目链接: Codeforces261D 题目大意:$k$次询问,每次给出一个长度为$n$的序列$b$及$b$中的最大值$maxb$,构造出序列$a$为$t$个序列$b$连接而成,求$a$的最长上升子 ...
随机推荐
- 51nod1434 区间LCM
将n!标准分解.m!/n!必定需要包含n!的分解式.对于每个质数枚举最小的答案,然后总的取最大. #include<cstdio> #include<cstring> #inc ...
- wx处理鼠标事件
#include "MainFrame.h" BEGIN_EVENT_TABLE(MyFrame,wxFrame) EVT_LEFT_DOWN(MyFrame::OnMouseLe ...
- 中文分词系列(二) 基于双数组Tire树的AC自动机
秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自 ...
- aspose.word使用简单方法
概念介绍 使用aspose生成word报表步骤: 加载word模板 提供数据源 填充 加载模板 提供了4种重载方法 public Document(); public Document(Stream ...
- 给新centos系统虚拟机配置网络服务
记录下今天新建虚拟机的过程吧. 镜像:CentOS-6.3-x86_64-minimal; 虚拟机版本: vm 8.0 LET'S----------------------->GO 手动新建一 ...
- Android 下实现图片的移动
网上看到的demo,感觉很有趣,但是 实用性不是太强,记录一下. 源码下载地址:请戳这里---------------->
- Android 手写Binder 教你理解android中的进程间通信
关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难.今天就教你如何从 app层面来理解好Binder. 其实就从我们普通app开发者的角度来看,仅仅对于androi ...
- IconRes提供免费高质量的Material风格android官方图标库
连接地址: http://www.iconres.com/android/index.php
- distinguish and differentiate
According to Cambridge Dictionary distinguish:to recognize or understand the difference between two ...
- 有关loading share object file libjvm.so: xxxxx 的那些问题
今天在跑一个有关postgresql产品的测试,要测试postgresql的有关Mirroring Controller的功能. 在执行mc_ctl命令的时候,报错:error while loadi ...