1 条题解

  • 0
    @ 2022-6-5 10:27:34

    luogu

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ls k<<1
    #define rs k<<1|1
    typedef long long ll;
    using namespace std;
    const int N=1e6;
    ll n,m,cnt;
    ll lx[N<<2],ch[N][2],w[N<<4],tag[N<<4];//
    ll la[N<<2],ra[N<<2],dp[N][2];//
    struct node{
        ll l,r,h,id;//需要记录一个编号,因为需要排序
        bool operator < (const node &b) const {
            return h<b.h;//按高度从矮到高排序
        }
    }a[N];
    inline void read(ll &x){
        x=0;
        char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    }
    inline void update(ll k,ll x,ll y){
        tag[ls]=tag[k];
        w[ls]=tag[k];
        tag[rs]=tag[k];
        w[rs]=tag[k];
        tag[k]=0;
    }
    inline void change(ll k,ll x,ll y,ll l,ll r,ll val){
        if(x>r||y<l) return;
        if(x>=l&&y<=r){//区间赋值
            tag[k]=val;
            w[k]=val;
            return;
        }
        ll mid=x+y>>1;
        if(tag[k]) update(k,x,y);//区间赋值的标记下传
        change(ls,x,mid,l,r,val);
        change(rs,mid+1,y,l,r,val);
    }
    inline ll query(ll k,ll x,ll y,ll pos){
        if(x>pos||y<pos) return 0;
        if(x==y) return w[k];//单点查询,w记录当前区间对应最上方的木板编号
        ll mid=x+y>>1;
        if(tag[k]) update(k,x,y);
        return query(ls,x,mid,pos)+query(rs,mid+1,y,pos);
    }
    int main()
    {
        ll i,j,stx,sty;
        read(n),read(m);
        read(stx),read(sty);
        n++;//有一个起始位置
        a[n].l=a[n].r=stx;
        a[n].h=sty,a[n].id=n;
        la[n]=stx,ra[n]=stx;
        lx[++cnt]=a[n].l;
        for(i=1;i<n;i++){
            read(a[i].h),read(a[i].l),read(a[i].r);
            a[i].id=i;
            la[i]=a[i].l;
            ra[i]=a[i].r;//la[] ra[]记录原来i木板的左右端点位置,因为需要离散化。
            lx[++cnt]=a[i].l;//lx[] 为离散化数组
            lx[++cnt]=a[i].r;
        }
        sort(lx+1,lx+cnt+1);//离散化数组排序
        sort(a+1,a+1+n);//木板高度排序
        for(i=1;i<=n;i++){//区间离散化
            a[i].l=lower_bound(lx+1,lx+1+cnt,a[i].l)-lx;
            a[i].r=lower_bound(lx+1,lx+1+cnt,a[i].r)-lx;
        }
        for(i=1;i<=n;i++){//点查询,不再多说
            ch[i][0]=query(1,1,cnt,a[i].l);
            ch[i][1]=query(1,1,cnt,a[i].r);
            change(1,1,cnt,a[i].l,a[i].r,i);
        }
        memset(dp,0x3f,sizeof(dp));
        dp[0][0]=dp[0][1]=0;//显而易见的初始化
        for(i=1;i<=n;i++){
            if(a[i].h-a[ch[i][0]].h<=m){//如果大于m不能转移
                if(ch[i][0]){//编号为0这带到到达地面
                     dp[i][0]=min(dp[i][0],dp[ch[i][0]][0]+la[a[i].id]-la[a[ch[i][0]].id]+a[i].h-a[ch[i][0]].h);
                     dp[i][0]=min(dp[i][0],dp[ch[i][0]][1]+ra[a[ch[i][0]].id]-la[a[i].id]+a[i].h-a[ch[i][0]].h);//加了离散数组的方程,一点点小变化
                 }
                 else dp[i][0]=a[i].h;
            }
            if(a[i].h-a[ch[i][1]].h<=m){
                if(ch[i][1]){
                    dp[i][1]=min(dp[i][1],dp[ch[i][1]][0]+ra[a[i].id]-la[a[ch[i][1]].id]+a[i].h-a[ch[i][1]].h);
                    dp[i][1]=min(dp[i][1],dp[ch[i][1]][1]+ra[a[ch[i][1]].id]-ra[a[i].id]+a[i].h-a[ch[i][1]].h);
                }
                else dp[i][1]=a[i].h;
            }
        }///test
        printf("%d",min(dp[n][0],dp[n][1]));//最后答案为转移到起始位置 n 的值。
    }//刚好99行
    
    • 1

    信息

    ID
    442
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者