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$的最长上升子 ...
随机推荐
- Codeforces 435 A Queue on Bus Stop
题意:给出n队人坐车,车每次只能装载m人,并且同一队的人必须坐同一辆车,问最少需要多少辆车 自己写的时候想的是从前往后扫,看多少队的人的和小于m为同一辆车,再接着扫 不过写出来不对 后来发现把每一队的 ...
- 使用了BeanUtils的简单操作
直接获取对象的某个值et.createCell(BeanUtils.getProperty(o, eh.getFieldName())); 简单为对象某个字段赋值c.setCellValue(Bean ...
- Xdebug的安装与使用
php下搭配使用xdebug是十分好的组合,用于php的调试工作,下面分别介绍之: 1 WINDOWS下的安装 下载站点http://www.xdebug.org/ 要确定使用一个跟你的PHP配合 ...
- == Rickard Oberg & TheServerSide
看了Hani Suleiman和Rickard Oberg ,发现其实每个所谓的权威都应该有被质疑的绝对,可能往往权威会令人觉得理所应当
- 【英语】Bingo口语笔记(12) - Put系列
put off 推迟
- ubuntu 安装AMP环境的笔记 Prefork方式与fast-cgi方法
具体步骤如下: 系统:ubuntu 8.04 的发行版本 AMP with Prefork(mod-php5) 一.安装APACHE2 # sudo apt-get install ...
- Linux makefile教程之书写规则三[转]
书写规则———— 规则包含两个部分,一个是依赖关系,一个是生成目标的方法.在 Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来 ...
- Delphi 之前解析串口数据
//串口接收数据procedure TfrmClientMain.Comm1ReceiveData(Sender: TObject; Buffer: Pointer; BufferLength: Wo ...
- When not to automate 什么时候不进行自动化
The cornerstone of test automation is the premise that the expected application behavior is known. W ...
- 【JNI】OPUS压缩与解压的JNI调用(.DLL版本)
OPUS压缩与解压的JNI调用(.DLL版本) 一.写在开头: 理论上讲,这是我在博客园的第一篇原创的博客,之前也一直想找个地方写点东西,把最近做的一些东西归纳总结下,但是一般工程做完了一高兴就把东西 ...