测试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;
}

 

转载于:https://www.cnblogs.com/dancer16/p/6840805.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生就业服务平台管理系统按照操作主体分为管理员和用户。管理员的功能包括学生档案管理、字典管理、试卷管理、试卷选题管理、试题表管理、考试记录表管理、答题详情表管理、错题表管理、法律法规管理、法律法规收藏管理、法律法规留言管理、就业分析管理、论坛管理、企业管理、简历管理、老师管理、简历投递管理、新闻资讯管理、新闻资讯收藏管理、新闻资讯留言管理、学生信息管理、宣传管理、学生管理、职位招聘管理、职位收藏管理、招聘咨询管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生就业服务平台管理系统可以提高大学生就业服务平台信息管理问题的解决效率,优化大学生就业服务平台信息处理流程,保证大学生就业服务平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理新闻信息,管理大学生就业服务平台信息,包括考试管理,培训管理,投递管理,薪资管理等,可以管理新闻信息。 考试管理界面,管理员在考试管理界面中可以对界面中显示,可以对考试信息的考试状态进行查看,可以添加新的考试信息等。投递管理界面,管理员在投递管理界面中查看投递种类信息,投递描述信息,新增投递信息等。新闻信息管理界面,管理员在新闻信息管理界面中新增新闻信息,可以删除新闻信息。新闻信息类型管理界面,管理员在新闻信息类型管理界面查看新闻信息的工作状态,可以对新闻信息的数据进行导出,可以添加新新闻信息的信息,可以编辑新闻信息信息,删除新闻信息信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值