最大权值(树状数组/线段树优化dp)
小明在校园里种了n棵树排成一排,第i棵树有两个属性,高度h[i],价值a[i],保证每棵树的高度不同,现在学校要砍伐一些树,使得剩余的树高度单调递增,并且剩余的树价值最大,问价值最大是多少。
输入格式
第一行一个整数n
第二行n个整数,表示h[1],h[2],...h[n]
第三行n个整数w[1],w[2],...w[n]
1<=n<=2e5,1<=h[i]<=n,1<=w[i]<=1e9
输出格式
一个整数
输入/输出例子1
输入:
4
3 1 4 2
10 20 30 40
输出:
60
输入/输出例子2
输入:
1
1
10
输出:
10
样例解释
无
dp优化:如果dp根据前一段dp值进行更新,然后要对当前点更新,也就是 dp[i]=dp[i-1]+.....,然后有限制条件,例如 a[i]<a[j],才能让i的值给j,考虑线段树/树状数组进行优化,下标对应的就是a的最大值,存的值就是最优的dp[i]
类似最长上升子序列,但是朴素dp,O(n^2)肯定会炸,这里放出朴素dp:
定f[i]:前i个数,留下的树高度单调上升,留下的树的价值的和的最大值
我们可以枚举一个j,j从1~i-1,限制:h[j] < h[i]
满足限制后,转移就是 f[i]=max(f[i], f[j]+w[i])
初始化:从第i棵树往后开始选,前面的一律不管了,也就是 f[i]=w[i]
答案就是1~n的最大f[i]
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n, h[N], w[N];
long long f[N], ans=0;
int main()
{
scanf("%d", &n);
for (int i=1; i<=n; i++) scanf("%d", &h[i]);
for (int i=1; i<=n; i++) scanf("%d", &w[i]);
for (int i=1; i<=n; i++)
{
f[i]=w[i];
for (int j=i-1; j>=1; j--)
if (h[j]<h[i]) f[i]=max(f[i], w[i]+f[j]);
}
for (int i=1; i<=n; i++) ans=max(ans, f[i]);
printf("%lld", ans);
return 0;
}
/*
7
1 5 2 6 3 7 4
60 80 20 100 90 40 20
7
1 5 2 6 3 7 4
60 80 20 100 90 40 20
280
*/
发现这里无法对 i 这里做优化,那么只能对 j 做文章了
我们想要找到满足限制的前i-1个的f[j]的最大值,找到后对第i位修改
转换为区间查询,单点修改,线段树和树状数组都是可以的
这里用树状数组。
树状数组存的肯定是 f 的最大值嘛
不过这里下标对应的值将会有意义,下标的意义变成的树的高度(并且树的高度不是很大),那么这样转换,问题就迎刃而解了。
我们只需要找 1~h[i]-1 的区间内的最大值就是区间查询了。
那么单点修改也很简单了,把下标为 h[i] 的值更新一下最大值为 f[i]
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n, h[N];
long long f[N], ans=0, w[N], s[N];
int lowbit(int x)
{
return x&(-x);
}
void add(int x, long long y)
{
for (int i=x; i<=n; i+=lowbit(i)) s[i]=max(s[i], y);
}
long long query(int x)
{
long long res=0;
for (int i=x; i>=1; i-=lowbit(i)) res=max(s[i], res);
return res;
}
int main()
{
scanf("%d", &n);
for (int i=1; i<=n; i++) scanf("%d", &h[i]);
for (int i=1; i<=n; i++) scanf("%lld", &w[i]);
for (int i=1; i<=n; i++)
{
f[i]=max(w[i], w[i]+query(h[i]-1));
add(h[i], f[i]);
}
for (int i=1; i<=n; i++) ans=max(ans, f[i]);
printf("%lld", ans);
return 0;
}
/*
7
1 5 2 6 3 7 4
60 80 20 100 90 40 20
7
1 5 2 6 3 7 4
60 80 20 100 90 40 20
280
*/

浙公网安备 33010602011771号