• [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;
    }
    
    
  • 相关阅读:
    Hdu-5983 2016ACM/ICPC亚洲区青岛站 B.Pocket Cube 模拟
    Codeforces Round #300 F
    cf298F:状压dp+剪枝
    POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
    jzp线性筛及其简单应用
    Codeforces Round #299 (Div. 1)C. Tavas and Pashmaks (凸壳)
    Codeforces Round #236 (Div. 2)E. Strictly Positive Matrix(402E)
    【2012天津区域赛】部分题解 hdu4431—4441
    HDU4436---str2int 后缀树组(12年天津区域赛)
    Codeforces
  • 原文地址:https://www.cnblogs.com/hbyer/p/9832251.html
Copyright © 2020-2023  润新知