题目描述
给定一个长度为 n
的整数序列 a1,a2,…,an
。
请你选出一个该序列的严格上升子序列,要求所选子序列的各元素之和尽可能大。
请问这个最大值是多少?
输入格式
第一行包含整数 n
。
第二行包含 n
个整数 a1,a2,…,an
。
输出格式
输出最大的上升子序列和。
数据范围
对于前三个测试点,1≤n≤4
。
对于全部测试点, 1≤n≤105,1≤ai≤109
。
样例
输入样例1:
2
100 40
输出样例1:
100
输入样例2:
4
1 9 7 10
输出样例2:
20
算法1
参考文献
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=100010;
int n,m;
int w[N],q[N];
LL f[N];//以a[i]结尾的最大上升子序列集合的最大值
LL tr[N];//树状数组
int lowbit(int x)
{
return x&-x;
}
void add(int x,LL v)
{
for(int i=x;i<=m;i+=lowbit(i))tr[i]=max(tr[i],v);//和求和性质一样
}
LL query(int x)
{
LL res=0;
for(int i=x;i>=1;i-=lowbit(i))
res=max(res,tr[i]);//和求前缀和性质一样
return res;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&w[i]);
memcpy(q,w,sizeof w);
sort(q,q+n);//数组排序
m=unique(q,q+n)-q;//去重复元素完的大小
LL res=0;
for(int i=0;i<n;i++)
{
int x=lower_bound(q,q+m,w[i])-q+1;//数组元素映射成下标,下标从1开始
f[i]=query(x-1)+w[i];//比x小的数加上当前数的和
res=max(res,f[i]);
add(x,f[i]);//加到树状数组里面
}
printf("%lld\n",res);
return 0;
}