[luogu P1442] 铁球落地

题目链接

线段树(+dp).

先用线段树预处理出每个线段从左边和右边掉落到哪里,记为(f[i][0/1]).

然后记(g[i][0/1])为到达第(i)个线段的左边或右边所要的最小时间,注意这里并没有算纵坐标的掉落时间,因为这个可以在最后统计答案时加上一个初始的纵坐标。

然后转移时从上到下把线段排个序,分左右两种情况转移。这里注意下给出的限制,即掉落的高度小于(max)时才转移。

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
void read(int &x){
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';x*=f;
}
#define write(x) printf("%d
",x)
#define maxn 200050
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
struct segment_tree {
    int val[maxn<<3],tag[maxn<<3];
    void pushdown(int p) {
        if(!tag[p]) return ;
        tag[ls]=tag[rs]=val[ls]=val[rs]=tag[p],tag[p]=0;
    }
    void cover(int p,int l,int r,int x,int y,int v) {
        if(x<=l&&r<=y) return tag[p]=v,val[p]=v,void();
        pushdown(p);
        if(x<=mid) cover(ls,l,mid,x,y,v);
        if(y>mid) cover(rs,mid+1,r,x,y,v);
    }
    int query(int p,int l,int r,int x) {
        if(l==r) return val[p];
        pushdown(p);
        if(x<=mid) return query(ls,l,mid,x);
        else return query(rs,mid+1,r,x);
    }
}T;
struct data {int x,y,l,r,h;}a[maxn];
int n,mx,sx,sy,vec[maxn],f[maxn][2],g[maxn][2];
const int N = 200000;
int cmp(data a,data b){return a.h<b.h;}
int main(){
    read(n);read(mx),read(sx),read(sy);
    for(int i=1;i<=n;i++) {
        read(a[i].h),read(a[i].l),read(a[i].r);
        vec[++vec[0]]=a[i].l,vec[++vec[0]]=a[i].r;
    }
    sort(vec+1,vec+vec[0]+1);
    for(int i=1;i<=n;i++) {
        a[i].x=lower_bound(vec+1,vec+vec[0]+1,a[i].l)-vec;
        a[i].y=lower_bound(vec+1,vec+vec[0]+1,a[i].r)-vec;
    }
    //sort(a+1,a+n+1,[&](data a,data b){return a.h<b.h;});
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++) {
        f[i][0]=T.query(1,1,N,a[i].x),f[i][1]=T.query(1,1,N,a[i].y);
        if(a[i].h-a[f[i][0]].h>mx) f[i][0]=-1;
        if(a[i].h-a[f[i][1]].h>mx) f[i][1]=-1;
        T.cover(1,1,N,a[i].x,a[i].y,i);
    }
    int st=lower_bound(vec+1,vec+vec[0]+1,sx)-vec;
    int p=T.query(1,1,N,st);memset(g,63,sizeof g);
    g[p][0]=sx-a[p].l,g[p][1]=a[p].r-sx;
    for(int i=p;i;i--) {
        if(f[i][0]!=-1) {
            g[f[i][0]][0]=min(g[f[i][0]][0],g[i][0]+(!f[i][0]?0:a[i].l-a[f[i][0]].l));
            g[f[i][0]][1]=min(g[f[i][0]][1],g[i][0]+(!f[i][0]?0:a[f[i][0]].r-a[i].l));
        }
        if(f[i][1]!=-1) {
            g[f[i][1]][0]=min(g[f[i][1]][0],g[i][1]+(!f[i][1]?0:a[i].r-a[f[i][1]].l));
            g[f[i][1]][1]=min(g[f[i][1]][1],g[i][1]+(!f[i][1]?0:a[f[i][1]].r-a[i].r));
        }
    }
    //for(int i=n;i;i--) printf("%d %d
",g[i][0],g[i][1]);
    write(min(g[0][0],g[0][1])+sy);
    return 0;
}

原文地址:https://www.cnblogs.com/hbyer/p/9832251.html