#D.糖果镇
思路
-
时整个路径有两个拐点,分别是 -
设拐点
在第 列,拐点 在第 列,则路径上的数字总和为 ( 表示第i行 的前缀和, 表示第 行 的后缀和) -
把带有
和 的项分开,设 ,则 -
所以只要枚举
就可以
数据点分治
m=1
- 只能一直往前走,累加即可;
//m=1 if(m==1){ ans=0; for(int i=1;i<=n;i++) ans=(ans+in[1][i])%p; cout<<ans%p<<"\n"; return 0; }
m=2
- 预处理
,暴力枚举一个拐点即可(两行只有一个拐点)//m=2 else if(m==2){ ans=0; for(int i=1;i<=n;i++) ans=max(ans,(front[1][i]+front[2][n]-front[2][i-1])%p); cout<<ans%p<<"\n"; return 0; }
所有 的和 模数
- 按照正常DP来做就可以
- 为什么模数会对结果有影响:
- 如果
恰好等于 而 等于 ,那么同时模 后第一个的结果小于第二个,常规DP得到的却是第一个大于第二个,所以只有在取模对原结果无影响(原结果小于模数)时才能用常规DP
//sum<p else if(sum<p){ for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ dp[i][j]=max(dp[i-1][j],dp[i][j-1])+in[i][j]; } } cout<<dp[m][n]<<"\n"; return 0; } - 如果
m=3
-
按照上面的思路,
的 的 ,所以要按照一定顺序,把下标大于等于当前 的 找出来,和 区和,求最大值 -
求
的时候一步一取模,使得 ,所以 有 和 两种情况,对于给定的 属于 属于
值域线段树
- 和普通线段树类似,不过改成了动态开点
- 用值域线段树维护区间
中各个子区间内 的最大值 - 这里按照倒序(正序也可以)往线段树里插入
,再用前文分类讨论的两个区间区 的最大值与 想加,取最大值作为结果//线段树 struct Node{ int l,r; int lc,rc; int maxn; }t[40*N]; int cnt=1; void Push_up(int id){ t[id].maxn=-INF; if(t[id].lc) t[id].maxn=max(t[t[id].lc].maxn,t[id].maxn); if(t[id].rc) t[id].maxn=max(t[t[id].rc].maxn,t[id].maxn); } void Modify(int id,int pos){ if(t[id].l==t[id].r){ t[id].maxn=pos; return; } int mid=(t[id].l+t[id].r)/2; if(pos<=mid){ if(!t[id].lc){ t[id].lc=++cnt; t[cnt].l=t[id].l; t[cnt].r=mid; t[cnt].lc=0; t[cnt].rc=0; t[cnt].maxn=-INF; } Modify(t[id].lc,pos); } else{ if(!t[id].rc){ t[id].rc=++cnt; t[cnt].l=mid+1; t[cnt].r=t[id].r; t[cnt].lc=0; t[cnt].rc=0; t[cnt].maxn=-INF; } Modify(t[id].rc,pos); } Push_up(id); } int Query(int id,int l,int r){ if(l<=t[id].l && t[id].r<=r) return t[id].maxn; int mid=(t[id].l+t[id].r)/2; int ret=-1; if(t[id].lc && l<=mid) ret=max(ret,Query(t[id].lc,l,r)); if(t[id].rc && r>=mid+1) ret=max(ret,Query(t[id].rc,l,r)); return ret; } //m=3 ans=0; for(int i=n;i>=1;i--){ Modify(1,g[i]); int ret; ret=Query(1,0,p-1-f[i]); if(ret!=-1) ans=max(ans,f[i]+ret); ret=Query(1,p-f[i],p-1); if(ret!=-1) ans=max(ans,(f[i]+ret)%p); } cout<<ans<<"\n";
Code
#include <bits/stdc++.h> #define int long long using namespace std; const int INF=1e9; const int N=1e5+10; struct Node{ int l,r; int lc,rc; int maxn; }t[40*N]; int cnt=1; void Push_up(int id){ t[id].maxn=-INF; if(t[id].lc) t[id].maxn=max(t[t[id].lc].maxn,t[id].maxn); if(t[id].rc) t[id].maxn=max(t[t[id].rc].maxn,t[id].maxn); } void Modify(int id,int pos){ if(t[id].l==t[id].r){ t[id].maxn=pos; return; } int mid=(t[id].l+t[id].r)/2; if(pos<=mid){ if(!t[id].lc){ t[id].lc=++cnt; t[cnt].l=t[id].l; t[cnt].r=mid; t[cnt].lc=0; t[cnt].rc=0; t[cnt].maxn=-INF; } Modify(t[id].lc,pos); } else{ if(!t[id].rc){ t[id].rc=++cnt; t[cnt].l=mid+1; t[cnt].r=t[id].r; t[cnt].lc=0; t[cnt].rc=0; t[cnt].maxn=-INF; } Modify(t[id].rc,pos); } Push_up(id); } int Query(int id,int l,int r){ if(l<=t[id].l && t[id].r<=r) return t[id].maxn; int mid=(t[id].l+t[id].r)/2; int ret=-1; if(t[id].lc && l<=mid) ret=max(ret,Query(t[id].lc,l,r)); if(t[id].rc && r>=mid+1) ret=max(ret,Query(t[id].rc,l,r)); return ret; } int n,m,p; int ans,sum; int in[4][N]; int dp[4][N]; int front[3][N],back[N]; int f[N],g[N]; signed main(){ // freopen("1.in","r",stdin); cin>>n>>m>>p; t[1].maxn=-INF; t[1].l=0; t[1].r=p; t[1].lc=0; t[1].rc=0; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ cin>>in[i][j]; sum+=in[i][j]; } } for(int i=1;i<=2;i++){ for(int j=1;j<=n;j++){ front[i][j]=front[i][j-1]+in[i][j]; } } if(m==1){ ans=0; for(int i=1;i<=n;i++) ans=(ans+in[1][i])%p; cout<<ans%p<<"\n"; return 0; }else if(m==2){ ans=0; for(int i=1;i<=n;i++) ans=max(ans,(front[1][i]+front[2][n]-front[2][i-1])%p); cout<<ans%p<<"\n"; return 0; }else if(sum<p){ for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ dp[i][j]=max(dp[i-1][j],dp[i][j-1])+in[i][j]; } } cout<<dp[m][n]<<"\n"; return 0; } for(int i=n;i>=1;i--){ back[i]=back[i+1]+in[3][i]; } for(int i=1;i<=n;i++){ f[i]=(front[1][i]-front[2][i-1])%p; g[i]=(front[2][i]+back[i])%p; } ans=0; for(int i=n;i>=1;i--){ Modify(1,g[i]); int ret; ret=Query(1,0,p-1-f[i]); if(ret!=-1) ans=max(ans,f[i]+ret); ret=Query(1,p-f[i],p-1); if(ret!=-1) ans=max(ans,(f[i]+ret)%p); } cout<<ans<<"\n"; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话