P1070 [NOIP2009 普及组] 道路游戏
思考最朴素做法
其中,
初始化:
我们发现可以降维,第三维其实可以用前缀和维护。
用
定义
有
定义函数
时间复杂度
考虑单调队列
该单调区间内记录
求答案时取队首的
然而单调队列要满足一个性质无论何时都要满足单调性,所以我们发现不可以把所有的数都放到同一个单调队列,因为不同道路上的金币不同的时刻可能不同,若我们把他们放到同一个单调队列,可能会导致在第一个时刻从工厂一开始会更优,第二个时刻的时候从工厂二开始会更优(只有从第三个工厂到第四个工厂的道路在第二个时刻的金币足够多,而其他的道路的金币又足够少)。相信丧心病狂的出题人会构造的。
那么我们可以构造多个单调队列,单调队列
最后再在取每一个单调队列的队首计算答案取
上代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const ll N=1010,INF=1e16; ll n,m,p,tzy,ans=-INF; ll r[N][N],G[N]; ll sum[N][N],f[N][N]; ll w(ll wz){return ((wz%n+n)%n)==0?n:((wz%n+n)%n);} ll val(ll st,ll la,ll ti){return sum[w(st+ti)][la+ti]-sum[st][la];} ll head[N],tail[N]; struct jgt{ll gs,ks,pos;}q[N][N]; void init() { for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) f[i][j]=-INF; for(ll i=1;i<=n;i++) f[0][i]=-G[i],head[i]=1; } int main() { scanf("%lld %lld %lld",&n,&m,&p); for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++) scanf("%lld",&r[i][j]); for(ll i=1;i<=n;i++) scanf("%lld",&G[i]); for(ll i=1;i<=m;i++) for(ll j=1;j<=n;j++) sum[j][i]=sum[w(j-1)][i-1]+r[w(j-1)][i]; init(); for(ll i=1;i<=m;i++) { for(ll st=1;st<=n;st++) { while(head[w(st-i+1)]<=tail[w(st-i+1)]&&q[w(st-i+1)][tail[w(st-i+1)]].gs+val(q[w(st-i+1)][tail[w(st-i+1)]].ks,q[w(st-i+1)][tail[w(st-i+1)]].pos,i-q[w(st-i+1)][tail[w(st-i+1)]].pos)<f[i-1][st]+val(st,i-1,1)) tail[w(st-i+1)]--; q[w(st-i+1)][++tail[w(st-i+1)]]={f[i-1][st],st,i-1}; while(i-q[w(st-i+1)][head[w(st-i+1)]].pos>p) head[w(st-i+1)]++; } tzy=-INF; for(ll j=1;j<=n;j++) tzy=max(tzy,q[j][head[j]].gs+val(q[j][head[j]].ks,q[j][head[j]].pos,i-q[j][head[j]].pos)); for(ll j=1;j<=n;j++) f[i][j]=tzy-G[j]; } for(ll i=1;i<=n;i++) ans=max(ans,f[m][i]+G[i]); printf("%lld\n",ans); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现