51NOD1781 Pinball 【离散化+线段树】

来源:互联网 发布:淘宝店不开了怎么注销 编辑:程序博客网 时间:2024/06/06 02:05

1781 Pinball

基准时间限制:1 秒 空间限制:262144 KB 分值: 20 难度:3级算法题

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

xfause (题目提供者)


首先 需要发现 对任意一种漏斗组合
设to[i] = 从第i列扔下小球 小球最终掉落的位置
对任意i < j ,必定有 to[i] <= to[j]
所以 如果 to[1]==to[m] 小球从任意位置掉落 都到 to[1] 位置上

所以 问题转化为 使1和m位置扔下的小球 落在同样位置

不难发现 花销最小时 1和m扔出的球 都会经过最后一个漏斗 且 在之前 不会经过相同的漏斗

oneTo[i] = 从1扔出 经过第i个漏斗 需要的最少花费
mTo[i] = 从m扔出 经过i漏斗 的最少花费

所以 答案就 = min( oneTo[i] + mTo[i] - d[i] )

于是问题就转化为求oneTo[i] 和 mTo[i]
显然

oneTo[i] = min( oneTo[j] ) + d[i]     //其中a[i]<=c[j]<=b[i] 且 j < noneTo[i] = d[i]                       //a[i]==1

复杂度为O(n*n) 显然不理想

此处如果使用线段树 维护 从1扔出小球 从 [ posL,posR ] 位置掉出 的最小花销
每次查询O(log(n) )
于是复杂度为O(nlog(n) )

PS:显然m过大 果断离散化

#include<iostream>#include<stdlib.h>#include<stdio.h>#include<string>#include<vector>#include<deque>#include<queue>#include<algorithm>#include<set>#include<map>#include<stack>#include<time.h>#include<math.h>#include<list>#include<cstring>#include<fstream>#include<queue>#include<sstream>//#include<memory.h>using namespace std;#define ll long long#define ull unsigned long long#define pii pair<int,int>#define INF 1000000007#define pll pair<ll,ll>#define pid pair<int,double>const ll inf = 1e17;const int N = 100000 + 5;const int M = 3*N;int read(){    char c=getchar();int k=0;for (;c<48||c>57;c=getchar());    for (;c>47&&c<58;c=getchar()) k=(k<<3)+(k<<1)+c-48;return k;}ll rmq[M*4];//从[l,r]列掉下一个小球的最少花费int pot[N][4];struct ColHash{    int key,i,j;}colHash[3*N];bool operator<(const ColHash&a,const ColHash&b){    return a.key<b.key;}int Hash(int n,int m){//返回离散化后的列数    colHash[3*n]={1,-1,-1};    colHash[3*n+1]={m,-1,-1};    for(int i=0;i<n;++i){        for(int j=0;j<3;++j){            colHash[3*i+j]={pot[i][j],i,j};        }    }    sort(colHash,colHash+3*n+2);    int k=0;    for(int i=0;i<3*n+2;++i){        if(i==0||colHash[i].key!=colHash[i-1].key){            ++k;        }        if(colHash[i].i!=-1){            pot[colHash[i].i][colHash[i].j]=k;        }    }    return k;}void initRmq(int k,int l,int r){    rmq[k]=inf;    if(l!=r){        int mid = (l+r)/2;        initRmq(2*k+1,l,mid);        initRmq(2*k+2,mid+1,r);    }}void addNode(int k,int l,int r,int pos,ll v){    if(l<=pos&&pos<=r){        rmq[k]=min(rmq[k],v);        if(l!=r){            int mid=(l+r)/2;            if(pos<=mid){                addNode(2*k+1,l,mid,pos,v);            }            if(pos>=mid+1){                addNode(2*k+2,mid+1,r,pos,v);            }        }    }}ll query(int k,int l,int r,int posL,int posR){    if(posL<=l&&r<=posR){        return rmq[k];    }    ll ans=inf;    if(l!=r){        int mid=(l+r)/2;        if(mid>=posL){            ll tmp = query(2*k+1,l,mid,posL,posR);            ans=min(tmp,ans);        }        if(mid+1<=posR){            ll tmp=query(2*k+2,mid+1,r,posL,posR);            ans=min(tmp,ans);        }    }    return ans;}ll oneTo[N];//从第1列扔下 到穿过第i个漏斗 的最少花销ll mTo[N];//从第m列扔下 .....ll dp(int n,int m){    fill(oneTo,oneTo+n+1,inf);    initRmq(0,1,m);    addNode(0,1,m,1,0);//1扔下 花销0    for(int i=0;i<n;++i){        ll val = query(0,1,m,pot[i][0],pot[i][1]);        oneTo[i]=min(oneTo[i],pot[i][3]+val);        addNode(0,1,m,pot[i][2],oneTo[i]);    }    fill(mTo,mTo+n+1,inf);    initRmq(0,1,m);    addNode(0,1,m,m,0);    for(int i=0;i<n;++i){        ll val = query(0,1,m,pot[i][0],pot[i][1]);        mTo[i]=min(mTo[i],pot[i][3]+val);        addNode(0,1,m,pot[i][2],mTo[i]);    }    ll ans =inf;    for(int i=0;i<n;++i){        ans = min(ans,oneTo[i]+mTo[i]-pot[i][3]);    }    return ans>=inf?-1:ans;}int main(){    //freopen("/home/lu/Documents/r.txt","r",stdin);    //freopen("/home/lu/Documents/w.txt","w",stdout);    int n=read(),m=read();    //scanf("%d%d",&n,&m);    for(int i=0;i<n;++i){        for(int j=0;j<4;++j){            pot[i][j]=read();        }    }    m=Hash(n,m);    printf("%lld\n",dp(n,m));    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝天猫退货单号填错了怎么办 淘宝退货我把快递单号弄丢了怎么办 唯品会退货快递单号填错了怎么办 天猫换货写错运单号怎么办 训练衣舍的店铺名连接怎么办 兼职模特被骗去微整还贷了款怎么办 卖家已经发货了我要退款怎么办 卖家显示发货单号信息查不到怎么办 淘宝申请退款卖家发货了怎么办 咸鱼卖家不发货好会自动退款怎么办 淘宝卖家涨价后不发货怎么办 淘宝卖家发货选错在线下单怎么办 申请退款后卖家又虚假发货了怎么办 公司用淘宝没发票做账怎么办 淘宝网买了假货确认了怎么办? 吃了安眠药睡了一天还没有醒怎么办 淘宝买的东西退货快递弄丢了怎么办 在淘宝上已付钱店家说没货了怎么办 从淘宝物流寄东西到国外被扣怎么办 不是天猫的淘宝卖家不发货怎么办 微店违规说卖假冒商品怎么办 云集微店的商品没货了怎么办 淘宝买家被检测有虚拟交易怎么办 媒体声音突然没有声音了该怎么办 华为微信运动步数为零怎么办 淘宝店铺没货了客户拍了怎么办 房子涨价了卖家反悔不卖了怎么办 买的东西很贵质量不好怎么办 在淘宝开的店账号忘了怎么办 建了个淘宝优惠券群没人购物怎么办 刚开的淘宝店没有生意怎么办 房产代理公司不给渠道结佣金怎么办 天猫超过72小时不发货怎么办 流量魔盒苹果下载怎么打不开怎么办 淘宝包邮店铺新疆地区拍怎么办 淘宝客服当顾客要优惠时怎么办 微信手机号注册的找不到了怎么办 之前注册的微信找不到了怎么办 苹果ipad的id密码忘了怎么办 淘宝和支付宝用一张银行卡怎么办 淘宝卖家填写虚假物流信息怎么办