Educational DP Contest Q

Q - Flowers

原题链接:https://atcoder.jp/contests/dp/tasks/dp_q

题目大意:

n支花,第i支花的高为w[i],价值为v[i],其中每支花的高度都不相同,范围在1到n。求从给定的花的序列中找到一段高度递增的子序列,求这段子序列的价值最大值。

解题思路:

建立数组$dp,dp[i]$为取第i朵花时的最大价值,在求要第i支花时的最大值时,要找到他前边比他矮的花的价值最大值,然后$dp[i]=dp[j]+v[i]$,在找$dp[j]$时,不能遍历。因为高度在$1-n$这个范围里,所以可以建立一个树状数组来存储前i个花的价值,这样就可以在$logn$的时间内求出前i支花中高度在$1-(w[i]-1)$的价值的最大值。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define debug(a) cout<<#a<<":"<<a<<endl;
 5 const ll INF=0x3f3f3f3f;
 6 const ll N=1e6+7;
 7 const ll mod=1e9+7;
 8 ll maxn,minn;
 9 ll T,n,m;
10 ll dp[N];
11 ll w[N];
12 ll v[N];
13 
14 ll arr[N],ans[N]; //对应原数组和树状数组
15 
16 ll lowbit(ll x){
17     return x&(-x);
18 }
19 
20 void update(ll i,ll k){    //在i位置加上k
21     while(i<=n){
22         ans[i]=max(ans[i],k);
23         i=i+lowbit(i);
24     }
25 }
26 
27 ll query(ll i){        //求arr[1 - i]的最大值
28     ll res = 0;
29     while(i>0){
30         res=max(res,ans[i]);
31         i =i-lowbit(i);
32     }
33     return res;
34 }
35 
36 int main(){
37     cin>>n;
38     for(ll i=1;i<=n;i++){
39         scanf("%lld",w+i);
40     }
41     for(ll i=1;i<=n;i++){
42         scanf("%lld",v+i);
43     }
44     for(ll i=1;i<=n;i++){
45         dp[i]=v[i]+query(w[i]);
46         maxn=max(maxn,dp[i]);
47         update(w[i],dp[i]);
48     }
49     cout<<maxn<<endl;
50     return 0;
51 }
 
原文地址:https://www.cnblogs.com/meanttobe/p/12852839.html