【DP】【Greedy】[CodeForces - 581E] Kojiro and Furrari

来源:互联网 发布:苹果同步助手软件 编辑:程序博客网 时间:2024/06/06 09:08

CodeForces - 581E

分析:根据题意(f < e),只能向右走,如果向左走,必定还要向右走,会消耗更多的油。
f[i][1/2]表示以空油箱从i向右走需要消耗的93#/95#油;
因为要求尽量多使用编号较大的油,所以对于i,它的编号为ai,如果在它向右s以内有编号aj>=ai,最近的为j,则加油至正好能到达j,否则,加满,然后在保证编号尽量大的情况下到最远的一个加油站加油。

可以用一个队列来保存离i距离<=s的加油站。

其实起点也可以当做一个汽油编号为3加油站,那么在dp的时候就可以直接用O(1)的时间得出答案,而起点不可以压入队列。

比官方题解好理解多了吧 :-D

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 200000int e,s,n,m,st,q[4][MAXN+10];    //3个队列存储编号分别为123的加油站typedef pair<int,int>pii;pii a[MAXN*2+10],f[MAXN*2+10],ans[MAXN+10];   //起点和加油站存在一起int main(){    int i,front[4],rear[4],j;    memset(f,0xff,sizeof f);    memset(ans,0xff,sizeof ans);    scanf("%d%d%d%d",&e,&s,&n,&m);    for(i=1;i<=n;i++)        scanf("%d%d",&a[i].second,&a[i].first);    for(i=1;i<=m;i++){        scanf("%d",&a[i+n].first);        a[i+n].second=3+i;        //存储询问顺序的同时和普通加油站作区别    }    sort(a+1,a+n+m+1);    for(i=1;i<=n+m;i++)        if(a[i].first>e)            break;    if(a[i].first==e)        i--;    a[i].first=e,a[i].second=3;    e=i;    f[e]=make_pair(0,0);    q[3][0]=e;    front[3]=rear[3]=0;    front[2]=front[1]=0;    rear[2]=rear[1]=-1;    for(i=e-1;i;i--){        int t=0x7fffffff;        while(front[3]<=rear[3]&&a[q[3][front[3]]].first-a[i].first>s)            front[3]++;        while(front[2]<=rear[2]&&a[q[2][front[2]]].first-a[i].first>s)            front[2]++;        while(front[1]<=rear[1]&&a[q[1][front[1]]].first-a[i].first>s)            front[1]++;        if(a[i].second>3){            for(j=3;j>0;j--)                if(front[j]<=rear[j]){                    if(j==1)                        ans[a[i].second-3]=make_pair(f[q[j][front[j]]].first-s+a[q[j][front[j]]].first-a[i].first,f[q[j][front[j]]].second);                    else if(j==2)                        ans[a[i].second-3]=make_pair(f[q[j][front[j]]].first,f[q[j][front[j]]].second-s+a[q[j][front[j]]].first-a[i].first);                    else                        ans[a[i].second-3]=make_pair(f[q[j][front[j]]].first,f[q[j][front[j]]].second);                    break;            }            if(!i)                ans[a[i].second]=make_pair(-1,-1);            continue;        }        for(j=3;j>=a[i].second;j--)            if(front[j]<=rear[j])                t=min(t,q[j][rear[j]]);        if(t==0x7fffffff)            for(;j;j--)                if(front[j]<=rear[j]){                    t=q[j][front[j]];                    break;                }        if(t==0x7fffffff)            break;        f[i]=f[t];        if(a[t].second>=a[i].second){            if(a[i].second==1)                f[i].first+=a[t].first-a[i].first;            else if(a[i].second==2)                f[i].second+=a[t].first-a[i].first;        }        else{            if(a[i].second==2){                f[i].second+=s;                f[i].first-=s-a[t].first+a[i].first;            }            else if(a[i].second==3){                if(a[t].second==2)                    f[i].second-=s-a[t].first+a[i].first;                else                    f[i].first-=s-a[t].first+a[i].first;            }        }        q[a[i].second][++rear[a[i].second]]=i;    }    for(i=1;i<=m;i++)        printf("%d %d\n",ans[i].first,ans[i].second);}
0 0
原创粉丝点击