hdu 2227 dp+树状数组优化

很容易可以想到状态转移方程:

  dp[i] = segma: dp[j] ( j < i && a[j] <= a[i] ), 其中dp[i]表示以a[i]结尾的不降子序列的个数。

但是n非常大,n^2的算法必然TLE,仔细想想其实式子右边是一个区间和的形式,即小于等于a[i]的a[j]的dp[j]的和,所以可以将a[i]离散化成t后将dp[i]的值存在t位置上,每次求解dp[i]就是查询一个前缀和,可以用树状数组来维护。

举个例子:对于1,50,13,34这四个数,离散化后变成了1,4,2,3。显然dp[1] = 1,所以我们在1位置插入1;而dp[2]就等于查询位置1到4(1+0+0+0)的和再加1,所以dp[2] = 2,我们在4位置插入2;dp[3]就等于(1+0)再加1,dp[3] = 2,我们在2位置插入2;dp[4]就等于(1+2+0)再加1为4,在位置3插入4,最后答案为整个数列的和:1+2+4+2=9.

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6
 7 typedef long long ll;
 8 const int N = 100001;
 9 const int MOD = 1000000007;
10 int c[N];
11
12 struct Node
13 {
14     ll s;
15     int id;
16 } node[N];
17
18 int lb( int i )
19 {
20     return i & -i;
21 }
22
23 void set( int i, int x )
24 {
25     while ( i < N )
26     {
27         c[i] += x;
28         c[i] %= MOD;
29         i += lb(i);
30     }
31 }
32
33 int get( int i )
34 {
35     int ans = 0;
36     while ( i > 0 )
37     {
38         ans += c[i];
39         ans %= MOD;
40         i -= lb(i);
41     }
42     return ans;
43 }
44
45 bool cmp1( Node n1, Node n2 )
46 {
47     if ( n1.s != n2.s ) return n1.s < n2.s;
48     return n1.id < n2.id;
49 }
50
51 bool cmp2( Node n1, Node n2 )
52 {
53     return n1.id < n2.id;
54 }
55
56 int main ()
57 {
58     int n;
59     while ( scanf("%d", &n) != EOF )
60     {
61         for ( int i = 1; i <= n; i++ )
62         {
63             scanf("%I64d", &node[i].s);
64             node[i].id = i;
65         }
66         sort( node + 1, node + 1 + n, cmp1 );
67         for ( int i = 1; i <= n; i++ )
68         {
69             node[i].s = i;
70         }
71         sort( node + 1, node + 1 + n, cmp2 );
72         memset( c, 0, sizeof(c) );
73         for ( int i = 1; i <= n; i++ )
74         {
75             int pn = node[i].s;
76             int nn = get(pn) + 1;
77             set( pn, nn );
78         }
79         printf("%d\n", get(n));
80     }
81     return 0;
82 }
时间: 2024-10-07 11:15:34

hdu 2227 dp+树状数组优化的相关文章

Codeforces 909 C. Python Indentation (DP+树状数组优化)

题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple statements. 相当于一般语句.(2)'f'语句:For statements. 相当于for循环,并且规定它的循环体不能为空. 然后给你一段没有缩进的Python程序,共n行(n <= 5000).问你添加缩进后,有多少种合法且不同的Python程序. 题解:题目解析 DP过去,如果第i个

HDU 2838 (DP+树状数组维护带权排序)

Reference: http://blog.csdn.net/me4546/article/details/6333225 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2838 题目大意:每头牛有个愤怒值,每次交换相邻两个数进行升序排序,$cost=val_{1}+val_{2}$,求$\min \sum cost_{i}$ 解题思路: 按输入顺序DP: 第i的值val的最小cost=当前数的逆序数个数*val+当前数的逆序数和 相当于每次只

bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化

3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 314  Solved: 132[Submit][Status] Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的

FZU2236 第十四个目标 dp+树状数组优化

分析:这种题烂大街,n^2,然后数据结构优化下到nlogn,离散化 #include <cstdio> #include <cstring> #include <queue> #include <set> #include <map> #include <stack> #include <cstdlib> #include <algorithm> #include <vector> #include

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

HDU 6447 - YJJ&#39;s Salesman - [树状数组优化DP][2018CCPC网络选拔赛第10题]

Problem DescriptionYJJ is a salesman who has traveled through western country. YJJ is always on journey. Either is he at the destination, or on the way to destination.One day, he is going to travel from city A to southeastern city B. Let us assume th

HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)

题目链接  2017 CCPC Harbin Problem K 题意  给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_{i}}$的最小值. 首先二分答案,那么每个物品的权值就变成了$x * b_{i} - a_{i}$ 在判断的时候先把那些权值为正的物品全部选出来, 然后记录一下从$1$开始可以覆盖到的最右端点的位置. 接下来开始DP,按照区间的端点升序排序(左端点第一关键字,右端点第二关键字) 问题转化为能否用剩

树形DP+树状数组 HDU 5877 Weak Pair

1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要离散化 4 5 #include <bits/stdc++.h> 6 using namespace std; 7 #define LL long long 8 typedef pair<int,int> pii; 9 const double inf = 12345678901234

LUOGU P2344 奶牛抗议 (树状数组优化dp)

传送门 解题思路 树状数组优化dp,f[i]表示前i个奶牛的分组的个数,那么很容易得出$f[i]=\sum\limits_{1\leq j\leq i}f[j-1]*(sum[i]\ge sum[j-1])$,但是这样的时间复杂度是$O(n^2)?$,所以考虑优化,发现必须满足$sum[i]\ge sum[j-1]?$才能进行转移,那么直接离散化后用树状数组维护一个前缀和即可. #include<iostream> #include<cstdio> #include<cstr