其他分享
首页 > 其他分享> > 最长上升子序列和

最长上升子序列和

作者:互联网

我们发现如果用dp来做的话
时间复杂度是O(n*n)
考虑数据范围一定会TLE所以我们用树状数组来优化
第二个代码是用线段树来优化的
当然了,还要用到离散化操作
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,w[100010],res,f[100010];
int tr[1000010];
vector<int>xs;

int get(int x){
    return lower_bound(xs.begin(),xs.end(),x)-xs.begin()+1;
}

int lowbit(int x){
    return x&-x;
}

void add(int x,int v){
    for(int i=x;i<=n;i+=lowbit(i)){
        tr[i]=max(tr[i],v);
    }
}

int query(int x){
    int sum=0;
    for(int i=x;i;i-=lowbit(i)){
        sum=max(sum,tr[i]);
    }
    return sum;
}

signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        xs.push_back(w[i]);
    }
    sort(xs.begin(),xs.end());
    xs.erase(unique(xs.begin(),xs.end())  ,  xs.end());
    for(int i=1;i<=n;i++){
        int k=get(w[i]);
        f[i]=query(k-1)+w[i];
        res=max(f[i],res);
        add(k,f[i]);
    }
    cout<<res;
}

这第二篇题解使用线段树写的
直接用线段树去更新,而没有再开一个dp数组去维护

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100010;
vector<int>xs;
int f[N],w[N],n;
struct node{
    int l,r,maxx;
}tr[N*4];

int get(int x){
    return lower_bound(xs.begin(),xs.end(),x)-xs.begin()+1;//线段树数组下标要从1开始所以要加1
    //清测不加1就wa了
    //return lower_bound(xs.begin(),xs.end(),x)-xs.begin();
}

void pushup(int u){
    tr[u].maxx=max(tr[u<<1].maxx,tr[u<<1|1].maxx);
}

void build(int u,int l,int r){
    if(l==r)tr[u]={l,r,0};
    else{
        tr[u]={l,r,-1};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        pushup(u);
    }
}

void modify(int u,int l,int r,int v){
    if(tr[u].l>=l&&tr[u].r<=r)tr[u].maxx=v;
    else{
        int mid=tr[u].l+tr[u].r>>1;
        if(mid>=l)modify(u<<1,l,r,v);
        if(mid<r)modify(u<<1|1,l,r,v);
        pushup(u);
    }
}

int query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r)return tr[u].maxx;
    else{
        int mid=tr[u].l+tr[u].r>>1;
        int res=0;
        if(mid>=l)res=query(u<<1,l,r);
        if(mid<r)res=max(res,query(u<<1|1,l,r) );
        pushup(u);
        return res;
    }
    
    
}

signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        xs.push_back(w[i]);
    }
    sort(xs.begin(),xs.end());
    xs.erase(unique(xs.begin(),xs.end() ),xs.end()  );
    build(1,1,n);
    for(int i=1;i<=n;i++){
        int k=get(w[i]);
        if(k==1){
            modify(1,k,k,w[i]);
            continue;
        }
        int vmax=query(1,1,k-1);
        modify(1,k,k,vmax+w[i]);
    }
    //其实单点修改也是可以的
    cout<<query(1,1,n);
}

标签:begin,end,int,tr,long,序列,xs,上升,最长
来源: https://blog.csdn.net/supreme567/article/details/117969488