树状数组 + dp

//CodeForces 314C
//分析:相当于求给定序列的不降子序列的个数,从一个空序列开始将得到的不降子序列不断的延长是典型的做法,则dp[i]表示以第 i 个元素结尾的序列
//思路:O(n^2) 的做法,dp[i] = sum(dp[j]]) (a[j] <= a[i] && j <= i),求和过程用掉了 O(n) 的复杂度,用树状数组可以优化成 O(logn),需要先处理出每个元素在原来的序列中的大小顺序,最终复杂度 O(nlogn)。

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "algorithm"
 5 using namespace std;
 6 int n;
 7 struct st
 8 {
 9     int ans, rank, pos;
10 } a[100010];
11 int tot;
12 bool cmp_1(st a, st b)
13 {
14     return a.ans < b.ans;
15 }
16 bool cmp_2(st a, st b)
17 {
18     return a.pos < b.pos;
19 }
20
21 inline int lowbit(int p)
22 {
23     return p&-p;
24 }
25 const int mod = 1000000007;
26
27 const int maxn = 100010;
28 int t[maxn], element[maxn];
29 void add(int p, int x)
30 {
31     int i;
32     for(i = p; i <= tot; i += lowbit(i)) {
33         t[i] += x;
34         t[i] %= mod;
35     }
36 }
37
38 __int64 sum(int p)
39 {
40     int i, res = 0;
41     for(i = p; i >= 1; i -= lowbit(i)) {
42         res += t[i];
43         res %= mod;
44     }
45     return res;
46 }
47
48 int main()
49 {
50     int i, j;
51     scanf("%d", &n);
52     for(i = 1; i<=n; ++i) {
53         scanf("%d", &a[i].ans);
54         a[i].pos = i;
55     }
56     sort(a+1, a+1+n, cmp_1);
57     tot = 1;
58     a[1].rank = 1;
59     for(i = 2; i<=n; ++i) {
60         if(a[i].ans!=a[i-1].ans)
61             a[i].rank = ++tot;
62         else
63             a[i].rank = tot;
64     }
65     sort(a+1, a+1+n, cmp_2);
66     int tmp;
67     for(i = 1; i<=n; ++i) {
68         tmp = (sum(a[i].rank)*a[i].ans%mod+a[i].ans)%mod;   //a[i].ans 是对空串的延长,因为 树状数组 不能计算到 t[0],不然就不用特殊处理空串的情况了
69         add(a[i].rank, (tmp-element[a[i].rank]+mod)%mod);   //减去重复计算值,即上一次的计算值
70         element[a[i].rank] = tmp;   //记录上一次的计算值
71     }
72     printf("%d\n", sum(tot));
73 }
时间: 2024-10-14 13:29:28

树状数组 + dp的相关文章

hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 481    Accepted Submission(s): 245 Problem Description You were driving along a highway when you got caught by the road p

hdu4455之树状数组+DP

Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1571    Accepted Submission(s): 459 Problem Description XXX has an array of length n. XXX wants to know that, for a given w, what is

Codeforces 597C. Subsequences (树状数组+dp)

题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长度为j的上升子序列个数,但是dp数组是在树状数组的update函数中进行更新. update(i, val, j)函数表示在i的位置加上val,更新dp[i][j]. sum(i, j)就是求出末尾数字小于等于i 且长度为j的子序列有多少个. 1 //#pragma comment(linker,

【树状数组+dp+离散化】Counting Sequences

https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/G [题意] 给定一个数组a,问这个数组有多少个子序列,满足子序列中任意两个相邻数的差(绝对值)都不大于d. [思路] 首先,朴素的dp思想: dp[i]为以a[i]结尾的子问题的答案,则dp[i]=sum(dp[k]),k<i&&|a[k]-a[i]|<=d 但是时间复杂度为O(n^2),会超时. 我们可以这样想: 如果数组a排好序后,dp[i]就是区间(a[

hdu5125 树状数组+dp

hdu5125 他说的是n个人每个人都有两个气球a,b,气球各自都有相应的体积,现在让他们按照序号排列好来,对他们的a气球体积值计算最长上升子序列,对于这整个排列来说有m次机会让你将a气球替换成b气球(允许不使用完),问最后的最长上升子序列 的长度是多少,哈哈,当然用dp的思想我们很容易就能知道状态的转移 dp[1000][1000][2],但是苦于状态转移的复杂度太大了达到了 n*n*m肯定受不了,那好我们可以列出这个方程的转移方法 (0表示a气球1为b气球) dp[i][j][0]=max(

POJ 3378 Crazy Thairs(树状数组+DP)

[题目链接] http://poj.org/problem?id=3378 [题目大意] 给出一个序列,求序列中长度等于5的LIS数量. [题解] 我们发现对于每个数长度为k的LIS有dp[k][i][a[i]]=dp[k-1][i-1][0~a[i]-1] 我们用5个树状数组维护不同长度的LIS,递推即可,注意答案超过LL,需要用大数. [代码] #include <cstdio> #include <algorithm> #include <cstring> usi

hdu 2227 树状数组+dp

题意是求一个数列的不递减的子序列的个数: 很显然,如果只用dp来做的话时间是O(n*n) 因为dp[i]为前i个数可能的方案,则状态转移方程为dp[i]=sum(dp[j],j<i&&num[j]<=num[i])+1 对小数据坑定能过 但大数据就超时了,这里用到了树状数组来优化: 先对num按数来进行排序,(这道题因为数据较大  用到了离散化) 因为更新是是按原序更新的,及i之前的num[j]一定比num[i]小,维护了不递减的原则,更新是从mark[i](表示原序列i在排序

【树状数组+dp】HDU 5542 The Battle of Chibi

http://acm.hdu.edu.cn/showproblem.php?pid=5542 [题意] 给定长为n的序列,问有多少个长为m的严格上升子序列? [思路] dp[i][j]表示以a[i]结尾的长度为j的严格上升子序列有多少个 dp[i][j]=sum{dp[k][j-1]},k小于i且a[k]<a[i] 区间dp,复杂度为O(n^3) 会超时,第三层循环求和用树状数组加速 时间复杂度为O(n^2logn) 离散化的时候排序后不去重(否则WA) [Accepted] #include<

POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP

Crazy Thairs Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6598   Accepted: 1636 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ≤ N ≤ 50000) numbers, which  are no more than 109, Crazy Thair is a g