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$的最长上升子 ...
随机推荐
- GUI for git|SourceTree|入门基础
原文链接:http://www.jianshu.com/p/be9f0484af9d 目录 SourceTree简介 SourceTree基本使用 SourceTree&Git部分名词解释 相 ...
- WEBUS2.0 In Action - 搜索操作指南 - (3)
上一篇:WEBUS2.0 In Action - 搜索操作指南(2) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(4) 3. 评分机制 (Webus.Search.IHitSc ...
- UVa 11520 Fill the Square 填充正方形
在一个 n * n 网格中填了一些大写字母,你的任务是把剩下的格子中也填满大写字母,使得任意两个相邻格子(即有公共边的格子)中的字母不同.如果有多重填法,则要求按照从上到下,从左到右的顺序把所有格子连 ...
- OpenGL学习之路(三)
1 引子 这些天公司一次次的软件发布节点忙的博主不可开交,另外还有其它的一些事也占用了很多时间.现在坐在电脑前,在很安静的环境下,与大家分享自己的OpenGL学习笔记和理解心得,感到格外舒服.这让我回 ...
- 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.2.Oracleasm Createdisk ASM磁盘失败:Instantiating disk: failed
1.错误信息:Instantiating disk: failed [root@linuxrac1 /]# /usr/sbin/oracleasm createdisk OCR_VOTE /dev/s ...
- library cache lock和cursor: pin S wait on X等待
1.现象: 客户10.2.0.4 RAC环境,出现大量的library cache lock和cursor: pin S wait on X等待,经分析是由于统计信息收集僵死导致的.数据库在8点到9点 ...
- 开发框架XUtils
xUtils 包含了很多实用的android工具. xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的O ...
- OSX 10.10安装教程。
现在苹果已经放出了OS X 10.9 Mavericks第一个开发者预览版,从Mac App Store中获得的安装程序,可以在10.8的系统中直接进行升级,原有文件都会保留.但是要想制作成一个10. ...
- git 换行符问题
git 换行符问题 在windows环境中 对于autocrlf = false 不会激发 关于换行符的处理 对于autocrlf = true 会在提交是将LF替换成CRLF 切出时时CRLF 对于 ...
- 【转载】Python中如何高效实现两个字典合并,三种方法比较。
本文转载自:http://www.pythoner.com/13.html Python中将两个字典进行合并操作,是一个比较常见的问题.本文将介绍几种实现两个字典合并的方案,并对其进行比较. 对于这个 ...