P11290Solution
a_sad_soul · · 题解
写的时候看成起点也是给定的还有救吗 QAQ
注意到
那么接下来考虑怎么转移。
分情况将几种类型递推 比如
初始化
然后预处理完找与终点最近的一个加油站枚举因数求最小值即可。
然后愉快的发现 MLE 了。
本题卡了空间所以要滚动数组滚掉第一维,把询问离线下来再转移即可。
时间复杂度是
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+10;
double f[MAXN][50][41];
double p[MAXN],t[MAXN],x[MAXN];
int n,q;
double ms[50][41];
double ans[MAXN];
struct ask{
double y;int id;
};
vector<ask>Q;
int main(){
scanf("%d%d",&n,&q);
for(int i=0;i<=49;++i)for(int j=0;j<=40;++j)f[0][i][j]=1e18;
f[0][0][0]=0;
for(int i=1;i<=n;++i)scanf("%lf%lf%lf",&p[i],&t[i],&x[i]);
ms[0][0]=1;
for(int i=1;i<=49;++i)ms[i][0]=ms[i-1][0]*2.0;
for(int i=0;i<=49;++i)
for(int j=1;j<=40;++j)
ms[i][j]=ms[i][j-1]*3.0;
for(int i=1;i<=q;++i){
double y;scanf("%lf",&y);Q.push_back(ask{y,i});
}
sort(Q.begin(),Q.end(),[](ask a,ask b){return a.y<b.y;});
int i=0;
p[n+1]=1e18;
for(ask a:Q){
while(p[i+1]<a.y){++i;
for(int j=0;j<=49;++j)
for(int k=0;k<=40;++k){
f[i&1][j][k]=f[(i&1)^1][j][k]+((p[i]-p[i-1])/ms[j][k]);
if(x[i]==1)continue;
if(x[i]==2&&j>0)f[i&1][j][k]=min(f[i&1][j][k],f[(i&1)^1][j-1][k]+t[i]+((p[i]-p[i-1])/ms[j-1][k]));
if(x[i]==3&&k>0)f[i&1][j][k]=min(f[i&1][j][k],f[(i&1)^1][j][k-1]+t[i]+((p[i]-p[i-1])/ms[j][k-1]));
if(x[i]==4&&j>1)f[i&1][j][k]=min(f[i&1][j][k],f[(i&1)^1][j-2][k]+t[i]+((p[i]-p[i-1])/ms[j-2][k]));
}
}ans[a.id]=1e18;
for(int j=0;j<=49;++j)
for(int k=0;k<=40;++k)
ans[a.id]=min(ans[a.id],(a.y-p[i])/ms[j][k]+f[i&1][j][k]);
}
for(int i=1;i<=q;++i)printf("%.9lf\n",ans[i]);
return 0;
}