zoukankan      html  css  js  c++  java
  • 测试1T3

    [提交][状态][讨论版]

    题目描述

    小天才lyk喜欢玩一个叫pinball的游戏。游戏规则如下:
    Pinball的游戏界面由m+2行、n列组成。第一行在顶端。一个球会从第一行出发,开始垂直下落,lyk会得到一个积分当他击中一个球的时候。
    小天才lyk觉得这太困难了,于是在界面中放入了一些漏斗,一共有m个漏斗分别放在第2~m+1行,第i个漏斗的作用是把经过第i+1行且列数在Ai~Bi之间的球将其移到第Ci列。
    但是使用每个漏斗都是需要付钱的,第i个漏斗需要支付Di的价钱,lyk需要保留一些漏斗,使得球无论从第一行的哪一列开始放,都只可能到达第m+2行的唯一一列。同时,lyk希望花费最小的价钱。

    输入

    第一行两个数,m和n
    接下来m行,第i+1行描述第i个漏斗的属性,Ai,Bi,Ci,Di(1<=Ai<=Ci<=Bi<=n,1<=Di<=1000000000)。

    输出

    若不存在一种方案能满足条件则输出-1,否则输出最小话费。

    样例输入

    5 6
    2 4 3 5
    1 2 2 8
    3 6 5 2
    4 6 4 7
    2 4 3 10
    
    
    
    3 5
    2 4 3 10
    1 3 1 20
    2 5 4 30
    

    样例输出

    25
    
    
    -1
    

    提示

    【样例解释1】



    如图,只需使用第2、4、5个漏斗即可。


    【数据范围】

    对于20%的数据,m<=10,n<=1000

    对于 40%的数据,m<=200

    对于60%的数据,m<=1000

    对于100%的数据,m<=100000,2<=n<=1000000000

     
    原题等价于第一列和第n列最终掉在同一列上
    l[i]表示从第1列到第i列最后使用漏斗i到达c[i]的最小花费
    l[i]=min(l[j]:a[i]<=c[j]<=b[i]+d[i]);
    这是个离散化的rmq问题
    用线段树就行
    离散化~~
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    #define ll long long
    const ll INF=(ll)1<<60;
    #define N 110000
    int n,m,a[N],b[N],c[N],d[N],q[N];
    ll ans=INF;
    struct seg{
        ll Min[N*4],a[N];
        void build(int u,int l,int r){
            if(l==r){
                Min[u]=a[l];
                return;
            }
            int mid=(l+r)>>1;
            build(u*2,l,mid);
            build(u*2+1,mid+1,r);
            Min[u]=min(Min[u*2],Min[u*2+1]);
        }
        ll find(int u,int l,int r,int x,int y){
            if(x<=l && y>=r)return Min[u];
            if(x>r || y<l)return INF;
            int mid=(l+r)>>1;
            return min(find(u*2,l,mid,x,y),find(u*2+1,mid+1,r,x,y));
        }
        void change(int u,int l,int r,int x,ll w){
            if(l==r){
                Min[u]=min(w,Min[u]);
                return;
            }
            int mid=(l+r)>>1;
            if(x<=mid)change(u*2,l,mid,x,w);
            else change(u*2+1,mid+1,r,x,w);
            Min[u]=min(Min[u*2],Min[u*2+1]);
        }
    }t1,t2;
    int bin1(int k){
        int l=1,r=q[0];
        while(l<r){
            int mid=(l+r)/2;
            if(q[mid]>=k)r=mid;
            else l=mid+1;
        }
        return l;
    }
    int bin2(int k){
        int l=1,r=q[0];
        while(l<r){
            int mid=(l+r)/2+1;
            if(k>=q[mid])l=mid;
            else r=mid-1;
        }
        return l;
    }
    int main(){
        freopen("pinball.in","r",stdin);
        freopen("pinball.out","w",stdout);
        scanf("%d%d",&n,&m);
        q[++q[0]]=1;
        q[++q[0]]=m;
        for(int i=1;i<=n;i++)scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]),q[++q[0]]=c[i];
        sort(q+1,q+q[0]+1);
        q[0]=1;
        for(int i=2;i<=n+2;i++)
            if(q[i]!=q[q[0]])q[++q[0]]=q[i];
        m=q[0];
        for(int i=1;i<=q[0];i++){
            t1.a[i]=INF*(int)(i>1);
            t2.a[i]=INF*(int)(i<q[0]);
        }
        t1.build(1,1,q[0]);
        t2.build(1,1,q[0]);
        for(int i=1;i<=n;i++){
            a[i]=bin1(a[i]);
            b[i]=bin2(b[i]);
            c[i]=bin1(c[i]);
            ll f1=t1.find(1,1,q[0],a[i],b[i]),f2=t2.find(1,1,q[0],a[i],b[i]);
            ans=min(f1+f2+d[i],ans);
            t1.change(1,1,q[0],c[i],f1+d[i]);
            t2.change(1,1,q[0],c[i],f2+d[i]);
        }
        if(ans<INF)cout<<ans<<endl;
        else cout<<-1<<endl;
        return 0;
    }
  • 相关阅读:
    简单区分Vmware的三种网络连接模式(bridged、NAT、host-only)
    linux创建账户并自动生成主目录和主目录下的文件
    EF 通用数据层类
    html在线美化网站
    图片在页面中居中显示
    __dopostback的用法
    rdlc报表集锦
    .NET开源免费的功能强大控件库
    使用webclient上传下载实例
    消息队列将并发变串行
  • 原文地址:https://www.cnblogs.com/dancer16/p/6840805.html
Copyright © 2011-2022 走看看