The Monochrome Picture SGU - 458 线段树优化dp

博客介绍了如何使用线段树优化动态规划方法来解决SGU 458问题,该问题要求从给定序列中删除最少数量的元素,以确保相邻元素之间的绝对差不超过1。
摘要由CSDN通过智能技术生成

参考:https://vjudge.net/solution/2633272

题意:
给定一个序列,删除最少的数使得任意两个相邻的数的abs不会相差1,

看来自己还是不太熟悉线段树,原本居然不知道怎么处理这个地方的用线段树的优化..

#include<bits/stdc++.h>

using namespace std;
#define up 1000000
#define N 100050
#define LL long long
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define inf 0x3f3f3f3f
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ls,ll, md
#define rson rs,md + 1, rr

int n,dp[N],mx[up<<2],id[up<<2],c[N];
int ans[up<<2],last[up<<2];

void query(int i,int ll,int rr,int a,int b,int j){
    if(a>b)return;
    if(ll==a&&rr==b){
        if(mx[i]>dp[j])dp[j]=mx[i],last[j]=id[i];
    }
    else{
        if(b<=md)query(lson,a,b,j);
        else if(a>md)query(rson,a,b,j);
        else{
            query(lson,a,md,j);
            query(rson,md+1,b,j);
        }
    }
}
void update(int i,int ll,int rr,int a,int b,int c){
    if(ll==rr)mx[i]=b,id[i]=c;
    else{
        if(a<=md)update(lson,a,b,c);
        else update(rson,a,b,c);
        if(mx[ls]>mx[rs])
            mx[i]=mx[ls],id[i]=id[ls];
        else mx[i]=mx[rs],id[i]=id[rs];
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&c[i]);
    for(int i=1;i<=n;++i){
        last[i]=0,dp[i]=0;
        query(1,0,up,0,c[i]-2,i);
        query(1,0,up,c[i],c[i],i);
        query(1,0,up,c[i]+2,up,i);
        dp[i]++;
        update(1,0,up,c[i],dp[i],i);
    }
    query(1,0,up,0,up,n+1);
    printf("%d\n",n-dp[n+1]);
    int p=0;
    for(int i=last[n+1];i!=0;i=last[i])ans[p++]=i;
    for(p--;p>=0;--p){
        printf("%d ",c[ans[p]]);
    }puts("");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值