1 条题解
-
0
自动搬运
来自洛谷,原作者为

Miko35
阿玮你又在打电动喔,去看会书好不好搬运于
2025-08-24 22:29:34,当前版本为作者最后更新于2022-07-20 11:03:56,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意
个加油站,第 与 个之间距离 个单位长度,第 个加油站加单位油量需要花费 的代价。
车只能向右走,走 单位长度要用 单位油量,用完不能走。加油不能超过油量上限。
组询问,每次给出 表示一辆车从 走到 并且油量上限为 需要花费的最小代价。
,。
题解
感谢 @クトリ 大师的提点 /bx
令油量上限为 ,有一个贪心:找到当前位置后第一个价格比它小的位置 ,加油至能走到 为止;若到 的距离 ,则加满 然后往后走一步。
考虑如何维护这个贪心:固定右端点,从右往左扫描左端点,维护价格递减的单调栈(为方便表述,令栈中元素是位置),栈顶即要找的位置。令当前位置为 , 加入单调栈后,策略的变化是用 替换从 到栈顶的前 个单位的油,不足则全部替换。原因是,我找到原单调栈中与 距离 的第一个位置,到达此位置时我一定没油,后面策略就不变了。
但询问的 不等,就要讨论单调栈每一段的贡献。具体而言,假设我此时弹出 ,弹出后的栈顶为 :
- :无事发生,当然无贡献。
- :将 单位油的价格由 替换为 ,贡献 。
容易发现这是个关于 的分段一次函数,线段树可以维护,这样就解决 Subtask 3 了。
对于区间 的询问,我们找出 中最小价格的位置 ,则 处的决策一定是加满油到走到 为止,这段路与「从 走到最后」的决策完全一致,所以 $\operatorname{ans}(l,r)=\operatorname{ans}(l,+\infty)-\operatorname{ans}(k,+\infty)+b_k(r-k)$。
只需要将右端点固定为最右边就可以算出 ,时间复杂度 。
#include<bits/stdc++.h> #define pbk emplace_back #define Mn(x,y) (b[x]<b[y]?x:y) #define FOR(i,a,b) for(int i=(a);i<=(b);++i) #define ROF(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; typedef long long ll; const int N=2e5+7,LG=18; int n,m,l,r,k,w,u[N],C,S[N],*c=S; struct BIT{ ll t[N],R; void upd(int x,ll v){for(;x<=C;x+=x&-x)t[x]+=v;} ll qry(int x){for(R=0;x;x&=x-1)R+=t[x];return R;} }K,B; ll d[N],D,sd[N][LG+1],mx,b[N],st[N][LG+1],ans[N]; struct qry{ int t,v,id; qry(int L,int V,int ID){t=L,v=V,id=ID;} void work(){ int h=lower_bound(u+1,u+C,t)-u; ans[id]+=v*(B.qry(h)+t*K.qry(h)); } }; vector<qry>q[N]; void mdf(int i,ll l,ll r,int vl){ int L=lower_bound(u+1,u+C,l=d[l]-d[i])-u,R=lower_bound(u+1,u+C,r=d[r]-d[i])-u; B.upd(L,-vl*l),B.upd(R,vl*r),K.upd(L,vl),K.upd(R,-vl); } signed main(){ scanf("%d%d",&n,&m); FOR(i,2,n+1)scanf("%lld",d+i),sd[i][0]=d[i],d[i]+=d[i-1]; FOR(i,1,n)scanf("%lld",b+i),st[i][0]=i; st[1+n][0]=1+n; FOR(w,1,LG)FOR(i,1<<w,1+n){ st[i][w]=Mn(st[i][w-1],st[i-(1<<(w-1))][w-1]); sd[i][w]=max(sd[i][w-1],sd[i-(1<<(w-1))][w-1]); } FOR(i,1,m){ scanf("%d%d%d",&l,&r,u+i),k=w=r,D=0; ROF(j,__lg(w),0)if(w-(1<<j)>=l)D=max(D,sd[w][j]),w-=(1<<j); if(D>u[i]){ans[i]=-1;continue;} q[l].pbk(u[i],1,i),w=r; ROF(j,__lg(w),0)if(w-(1<<j)>=l-1&&d[r]-d[w-(1<<j)+1]<=u[i]){ k=Mn(k,st[w][j]),w-=(1<<j); } q[k].pbk(u[i],-1,i),ans[i]=b[k]*(d[r]-d[k]); } sort(u+1,u+m+1),C=unique(u+1,u+m+1)-u,*c=n+1; ROF(i,n+1,1){ for(;c!=S&&b[i]<b[*c];--c)mdf(i,*c,c[-1],-b[*c]); mdf(i,i,*c,b[i]),*(++c)=i; for(qry k:q[i])k.work(); } FOR(i,1,m)printf("%lld\n",ans[i]); return 0; }
- 1
信息
- ID
- 6514
- 时间
- 1500ms
- 内存
- 500MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者