最长上升子序列和
作者:互联网
我们发现如果用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