洛谷p1020[最长不上升序列--树状数组dp/stl

https://www.luogu.org/fe/problem/P1020

第一种:树状数组

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

void add(int x,int c){ 
    for(int i=x;i<=maxn;i+=lowbit(i)) f[i]=max(f[i],c);//维护最大值 
}

int query(int x){
    int res=0;
    for(int i=x;i>=1;i-=lowbit(i)) res=max(res,f[i]);//求以小于等于x的数为结尾的最长不上升子序列的长度的最大值 
    return res;
}

int main(){
    while(scanf("%d",&a[++n])!=EOF) maxn=max(maxn,a[n]);
    n--;//要-1,不然n就不是正确的n了 
    for(int i=n;i>=1;i--){//从后往前循环 
        int q=query(a[i])+1;//查询以小于等于x的数为开头的最长不上升子序列的长度的最大值
        add(a[i],q);//这个最大值+1就是以当前这个数开头的最长不上升子序列的长度,丢到树状数组里面去 
        ans1=max(ans1,q); 
    }
    printf("%d\n",ans1);
    memset(f,0,sizeof(f));//还是memset一下比较保险 
    for(int i=1;i<=n;i++){//从前往后循环 
        int q=query(a[i]-1)+1;//查询以小于(没有等于!!!)x的数为结尾的最长上升子序列的长度的最大值
        add(a[i],q);//这个最大值+1就是以当前这个数结尾的最长上升子序列的长度,丢到树状数组里面去 
        ans2=max(ans2,q);
    }
    printf("%d\n",ans2);
}
int a[N],d1[N],d2[N],n;
int main() {
    while(cin>>a[++n]);n--;     //输入
    int len1=1,len2=1;      //初始长度为1
    d1[1]=a[1];     //用于求不上升序列长度
    d2[1]=a[1];     //用于求上升序列长度
    for(int i=2; i<=n; i++) {       //从a[2]开始枚举每个数(a[1]已经加进去了)
        if(d1[len1]>=a[i])d1[++len1]=a[i];      //如果满足要求(不上升)就加入d1
        else {      //否则用a[i]替换d1中的一个数
            int p1=upper_bound(d1+1,d1+1+len1,a[i],greater<int>())-d1;
            d1[p1]=a[i]; 
        }
        if(d2[len2]<a[i])d2[++len2]=a[i];       //同上
        else {
            int p2=lower_bound(d2+1,d2+1+len2,a[i])-d2;
            d2[p2]=a[i];
        }
    }
    cout<<len1<<endl<<len2;     //输出
    return 0;       //结束
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值