题目描述
Keith买了一辆新车,打算把自己的新车开到学校,给403的小伙伴们看看。
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#汽油。
由于Keith忙于研究SAM及其相关应用,所以他找到你来帮他完成这个任务。
第i个加油站坐标是Xi,油的种类是Ti
数据范围1 ≤ N , M ≤ 200000 , 0 ≤ Wi , Xi , E , S ≤ 10^9且Wi ≤ E , 1 ≤ Ti ≤ 3
贪心
显然,(性质1)车只会向右开,因为Wi ≤ E。
另外,(性质2)从车站i出发,开到满足t[j]>=t[i]的最近的一个车站j一定是最优的(最优不一定唯一,但肯定不存在更优)。
根据性质1
首先我们可以把车站根据坐标排序(从小到大),把坐标大于等于E的车站忽略(因为没有贡献),然后把学校视为坐标等于E且T=3的车站。
我们开3个vector,T=3放进vector3,T>=2放进vector1~2,T>=1放进vecotor1(只要满足都需要放进)
这个可以用于二分查找来优化dp
dp
设f[i][j]表示从第i个车站只通过T值>=j的车站到达学校至少需要增加多少油
当f[i][j]>0时就表示i不能只通过T值>=j的车站到达学校。
j只需从1枚举到T[i,因为有性质2。
然后如果一个家Wi能够到达学校,当且仅当从Wi到达的第一个T值>=1的车站i,满足f[i][0]+max(Xi-Wi-s,0)=0;
设从Wi到达的第一个T值>=2的车站为i1,从Wi到达的第一个T值=2的车站为i2
则92#汽油的最小消耗为s1=f[i1][0]+max(Xi1-Wi-S,0),95#汽油的最小消耗为f[i2][0]+max(Xi2-Wi-S,0)-s1
代码
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=200000+100;
struct ar{
int x,y;
friend bool operator <(ar x,ar y) {
return x.x<y.x;
}
} p[maxn];
int i,j,n,m,e,s,w[maxn];
int f[maxn][3];
vector<ar> a[3];
bool cmp(ar x,ar y){
return x.y<y.y;
}
int main(){
scanf("%d%d%d%d",&e,&s,&n,&m);
fo(i,1,n) {scanf("%d%d",&p[i].x,&p[i].y);p[i].x--;}
sort(p+1,p+1+n,cmp);
ar w;
fo(i,1,n) if (p[i].y<e)fo(j,0,p[i].x) {
w.x=p[i].y,w.y=i;
a[j].push_back(w);
}else {n=i-1;break;}
w.x=e,w.y=n+1;
fo(j,0,2) a[j].push_back(w);
fod(i,n,1){
w.x=p[i].y;
ar t=*upper_bound(a[0].begin(),a[0].end(),w);
f[i][0]=f[t.y][0]+max(t.x-w.x-s,0);
if (p[i].x>0){
t=*upper_bound(a[1].begin(),a[1].end(),w);
f[i][1]=f[t.y][1]+max(t.x-w.x-s,0);
if (p[i].x==2){
t=*upper_bound(a[2].begin(),a[2].end(),w);
f[i][2]=f[t.y][2]+max(t.x-w.x-s,0);
}
}
}
fo(i,1,m){
scanf("%d",&w.x);if (w.x==e) {printf("0 0\n");continue;}
ar t=*upper_bound(a[0].begin(),a[0].end(),w);
int g=f[t.y][0]+max(t.x-w.x-s,0);
if (g) {printf("-1 -1\n");continue;}
t=*upper_bound(a[1].begin(),a[1].end(),w);int t1=f[t.y][1]+max(t.x-w.x-s,0);
printf("%d ",t1);
t=*upper_bound(a[2].begin(),a[2].end(),w);
printf("%d\n",f[t.y][2]+max(t.x-w.x-s,0)-t1);
}
}