CF581E,JZOJ4689新车

来源:互联网 发布:linux tftp 搭建 编辑:程序博客网 时间:2024/04/27 08:31

题目描述

Keith家(多个)在城区,从城区到学校的路可以抽象成一个数轴,Keith家的坐标为W,学校的坐标为E。路上有很多加油站,每个加油站能提供92#,95#,98#三种汽油中的一种。由于Keith不缺钱,每到一个加油站,他都能加任意多的油。由于道路是双向的,Keith的车既能往左开,也能往右开。
1升汽油可以跑1千米,这与油的种类无关。车的油箱容量是S升,任何时候油箱中的油都不能超过S升,但是作为Keith大神的御用座驾,这台车有点与众不同,它的油箱中能同时存在多种汽油。出发时,油箱是装满98#汽油的。
众所周知的是,98#汽油最好,92#最差。由于Keith很爱惜自己的新车,所以他希望用尽可能少的92#汽油,如果有多种可能用的92#同样多,那就要求用的95#尽可能少。
现在Keith告诉你N个家的坐标Wi,学校的坐标E,以及路上所有加油站的坐标,求从各个家分别到学校的最优策略中,需要消耗的最少92#和95#汽油。

1 ≤ N , M ≤ 200000 , 0 ≤ Wi , Xi , E , S ≤ 10^9且Wi ≤ E , 1 ≤ Ti ≤ 3

分析

比赛的时候想到的贪心策略比较麻烦,没有简化,以致没法dp过去,而且那时候时间紧,暴力完后就赶紧想第一题了(也没写粗来···)。
首先把家和学校看成98加油站。然后贪心策略:从当前加油站出发,如果在s范围内有油品相同或者更好的,就走到最近的那个;如果没有,就尽量走远一点,并优先在油品比较好的加油站里停下加油,这里不一定加满。(当然不能停在另一个家)
然后设个f[i][0\1]表示在第i个加油站出发,此时车没油,要到达学校的所要用的92\95。从学校往左边跑就行了。

代码

#include<cstdio>#include<algorithm>using namespace std;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)const int N=2000005;struct rec{    int x,t,rev;}b[N];int e,s1,n,m,w[N],i,j,dur,s[4],d[4][N],f[N][2],ans[N][2],tt,tar,t[4];bool cmp(rec a,rec b){    return (a.x<b.x)||(a.x==b.x&&(a.t<b.t));}int main(){    freopen("car.in","r",stdin);    freopen("car.out","w",stdout);    scanf("%d %d %d %d",&e,&s1,&n,&m);    fo(i,1,n) scanf("%d%d",&b[i].t,&b[i].x);    b[n+1].x=e;    b[n+1].t=3;    tt=n+1;    fo(i,1,m)     {        scanf("%d",w+i);        b[++tt].x=w[i];        b[tt].t=4;        b[tt].rev=i;    }    sort(b+1,b+1+tt,cmp);    fo(i,1,tt)        if (b[i].x==e&&b[i].t==3)        {            tt=i;            break;        }    f[tt][0]=f[tt][1]=0;    s[1]=s[2]=s[3]=1;    t[1]=t[2]=t[3]=0;    t[3]=1;    d[3][s[3]]=tt;    fd(i,tt-1,1)    {        if (b[i+1].x==b[i].x&&b[i].t<b[i+1].t&&b[i+1].t!=4) continue;        fo(j,1,3)            while (s[j]<=t[j]&&b[d[j][s[j]]].x-b[i].x>s1) s[j]++;        tar=0;        fo(j,min(b[i].t,3),3)            if (s[j]<=t[j]&&(tar==0||b[d[j][t[j]]].x<b[d[tar][t[tar]]].x))                tar=j;        if (tar)        {            f[i][0]=f[d[tar][t[tar]]][0];            f[i][1]=f[d[tar][t[tar]]][1];            if (b[i].t<3)                 f[i][b[i].t-1]+=b[d[tar][t[tar]]].x-b[i].x;        }        else        {            fd(j,3,1)                if (s[j]<=t[j])                    break;            if (!j)            {                fo(j,1,i) f[j][0]=f[j][1]=-1;                break;            }            f[i][0]=f[d[j][s[j]]][0];            f[i][1]=f[d[j][s[j]]][1];            if (b[i].t<3)                f[i][b[i].t-1]+=s1;            f[i][b[d[j][s[j]]].t-1]-=s1-(b[d[j][s[j]]].x-b[i].x);        }        if(b[i].t!=4)               d[b[i].t][++t[b[i].t]]=i;    }    fo(i,1,tt)          ans[b[i].rev][0]=f[i][0],ans[b[i].rev][1]=f[i][1];    fo(i,1,m)        printf("%d %d\n",ans[i][0],ans[i][1]);}

反思

1,改题的时候太累了,改了一个小时,精神很重要。
2,贪心一定能简化就简化,这样写起来也容易点。
3,对于这个贪心不复杂的题目,大数据错就要多读程序,要在调试方法的耗时找个平衡点。

0 0