树状数组优化最长上升子序列
最长上升子序列比较暴力的写法是n2 的,实际上我们求得就是前面的比当前小的最长上升子序列的最大值;
树状数组可以优化它;
倒过来求就是最长下降子序列;
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+10; typedef double dd; typedef long long ll; ll n; ll a[maxn]; ll id[maxn]; ll f[maxn],g[maxn]; ll b1[maxn],b2[maxn]; int len; ll query_front(int x) { ll ans=0; for(;x;x-=x&(-x)) ans=max(b1[x],ans); return ans; } ll query_back(int x) { ll ans=0; for(;x;x-=x&(-x)) ans=max(b2[x],ans); return ans; } void add_front(int x,ll y) { for(;x<=len;x+=x&(-x)) b1[x]=max(b1[x],y); } void add_back(int x,ll y) { for(;x<=len;x+=x&(-x)) b2[x]=max(b2[x],y); } dd ans; int qw[maxn]; int main() { scanf("%lld",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); id[i]=a[i]; } sort(id+1,id+n+1); len=unique(id+1,id+n+1)-id-1; for(int i=1;i<=n;i++) qw[i]=lower_bound(id+1,id+len+1,a[i])-id; for(int i=1;i<=n;i++) { f[i]=query_front(qw[i]-1)+a[i]; g[n-i+1]=query_back(qw[n-i+1]-1)+a[n-i+1]; add_front(qw[i],f[i]); add_back(qw[n-i+1],g[n-i+1]); } return 0; }