• 51Nod 欢乐手速场1 A Pinball[DP 线段树]


    xfause (命题人)
     
    基准时间限制:1 秒 空间限制:262144 KB 分值: 20
    Pinball的游戏界面由m+2行、n列组成。第一行在顶端。一个球会从第一行的某一列出发,开始垂直下落,界面上有一些漏斗,一共有m个漏斗分别放在第2~m+1行,第i个漏斗的作用是把经过第i+1行且列数在Ai~Bi之间的球,将其移到下一行的第Ci列。 使用第i个漏斗需要支付Di的价钱,你需要保留一些漏斗使得球无论从第一行的哪一列开始放,都只可能到达第m+2行的唯一 一列,求花费的最少代价。
     
    (样例的图)
    (我们保留2,4,5即可,代价为5+3+12=20)
     
    Input
    第一行两个数,m和n。m<=100000,2<=n<=1000000000
    接下来m行,第i+1行描述第i个漏斗的属性,Ai,Bi,Ci,Di (1<=Ai<=Ci<=Bi<=n, 1<=Di<=1000000000)。
    Output
    若不存在一种方案能满足条件则输出-1,否则输出最小花费
    Input示例
    5 6
    3 5 4 8
    1 4 3 5
    4 6 5 7
    5 6 5 3
    3 5 4 12
    Output示例
    20

    最后一定经过同一个漏斗
    枚举最后经过哪个漏斗,然后求出第1列和第n列到达这个漏斗的最小花费就好了
    考虑DP L[i]和R[i]
    L[i]表示从1下落使用漏斗i到达C[i]的最小话费 L[i]=min{L[j] : A[i]<=C[j]<=B[i]}+D[i]}
    这种带修改的RMQ问题用个线段树就好了
    当然要离散化列啦
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define lson x<<1,l,mid
    #define rson x<<1|1,mid+1,r
    #define lc x<<1
    #define rc x<<1|1
    typedef long long ll;
    const int N=1e5+5,M=3e5+5;
    const ll INF=1e18;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,m,a[N],b[N],c[N],d[N];
    int mp[M];
    void iniMP(){
        sort(mp+1,mp+1+mp[0]);
        int p=0;mp[++p]=mp[1];
        for(int i=2;i<=mp[0];i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
        mp[0]=p;
    }
    int Bin(int v){
        int l=1,r=mp[0];
        while(l<=r){
            int mid=(l+r)>>1;
            if(mp[mid]==v) return mid;
            else if(v<mp[mid]) r=mid-1;
            else l=mid+1;
        }
        return 0;
    }
    ll t[M<<2];
    void build(int x,int l,int r){
        if(l==r) t[x]=INF;
        else{
            int mid=(l+r)>>1;
            build(lson);
            build(rson);
            t[x]=min(t[lc],t[rc]);
        }
    }
    void segCha(int x,int l,int r,int p,ll v){
        if(l==r) t[x]=min(t[x],v);//!!!
        else{
            int mid=(l+r)>>1;
            if(p<=mid) segCha(lson,p,v);
            else segCha(rson,p,v);
            t[x]=min(t[lc],t[rc]);
        }
    }
    ll segMin(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr) return t[x];
        else{
            ll re=INF;
            int mid=(l+r)>>1;
            if(ql<=mid) re=min(re,segMin(lson,ql,qr));
            if(mid<qr) re=min(re,segMin(rson,ql,qr));
            return re;
        }
    }
    ll L[N],R[N];
    void solve(){
        build(1,1,mp[0]);
        segCha(1,1,mp[0],1,0);
    //    printf("check %d %d
    ",segMin(1,1,mp[0],2,5),segMin(1,1,mp[0],1,5));
        for(int i=1;i<=n;i++){
            L[i]=segMin(1,1,mp[0],a[i],b[i])+d[i];        
            segCha(1,1,mp[0],c[i],L[i]);
            //printf("L %d %d
    ",i,L[i]);
        }
        
        build(1,1,mp[0]);
        segCha(1,1,mp[0],mp[0],0);
        for(int i=1;i<=n;i++){
            R[i]=segMin(1,1,mp[0],a[i],b[i])+d[i];
            segCha(1,1,mp[0],c[i],R[i]);
            //printf("R %d %d
    ",i,R[i]);    
        }
        
        ll ans=INF;
        for(int i=1;i<=n;i++) ans=min(ans,L[i]+R[i]-d[i]);
        if(ans<INF) printf("%lld",ans);
        else puts("-1");
    }
    int main(){
    //    freopen("in.txt","r",stdin);
        n=read();m=read();
        mp[++mp[0]]=1;mp[++mp[0]]=m;
        for(int i=1;i<=n;i++){
            mp[++mp[0]]=a[i]=read();
            mp[++mp[0]]=b[i]=read();
            mp[++mp[0]]=c[i]=read();
            d[i]=read();
        }
        iniMP();
        //for(int i=1;i<=mp[0];i++) printf("mp %d %d
    ",i,mp[i]);
        for(int i=1;i<=n;i++) a[i]=Bin(a[i]),b[i]=Bin(b[i]),c[i]=Bin(c[i]);
        solve();
    }




  • 相关阅读:
    Maven私服安装
    Maven运行的方式
    Maven传递依赖的范围
    Maven子模块
    Maven父工程
    Maven项目指定JDK版本
    Maven传递依懒
    Maven概念模型
    Swift -欢迎界面1页, 延长启动图片的显示时间(LaunchImage)
    Swift
  • 原文地址:https://www.cnblogs.com/candy99/p/6366603.html
Copyright © 2020-2023  润新知