陈大哥的NOIP模拟
8.19
Path
卢姥爷太强了!!!
(n+m−1)∗∑n+m−1i=1(Ai−Aavg)2
=……
=∑n+m−1i=1[(n+m−1)∗A2i]−∑n+m−1i=12∗Ai∗sum+sum2
=∑n+m−1i=1[(n+m−1)∗A2i]−2∗sum∗∑n+m−1i=1Ai+sum2
=∑n+m−1i=1[(n+m−1)∗A2i]−sum2
对于确定的sum,只需求出式子前一部分的最小值,可以用DP来做。f[i][j][k]表示到(i,j),目前所走路径的和为k,所走过路径的∑i+j−1i=1[(n+m−1)∗A2i]的最小值。
调试时出错的点:
1.因为初始值为正无穷,如果用DP只表示∑i+j−1i=1A2i的话,以为最后统计答案要乘一个n+m−1,那么没更新过答案的位置会爆掉int,导致最后答案为负值。
2.用k代表n+m−1时忘记了循环变量也用的k
3.第三位最大到1830(1900)就行,结果枚举边界设为了所有数的和,爆掉了
最终代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[33][33],f[33][33][2000],t;
int ans=2147483647,sum;
int main()
{
scanf("%d%d",&n,&m);
t=n+m-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
sum=1900;
memset(f,0x3f,sizeof(f));
f[1][1][a[1][1]]=a[1][1]*a[1][1]*t;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(i==1&&j==1) continue;
for(int k=a[i][j];k<=sum;k++)
{
f[i][j][k]=min(f[i][j-1][k-a[i][j]],f[i-1][j][k-a[i][j]])+a[i][j]*a[i][j]*t;
}
}
/* for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
for(int k=a[i][j];k<=sum;k++)
{
// cout<<i<<"*"<<j<<"*"<<k<<"*"<<f[i][j][k]<<endl;
}
}*/
for(int i=1;i<=sum;i++)
ans=min(ans,f[n][m][i]-i*i);
printf("%d\n",ans);
return 0;
}
考试时,这里写成了k−1
Rect
调到死亡。。。。
错点:
1.
不能用ST表维护一段区间的最小值
原因:
只用它向左扩展到最远位置中高度的最小值,会漏掉答案(假设红色是答案),只会计算到橙色的。
(考试时的错点)
2.
关于单调队列,等于的时候是要退出的。假如当前点进队之前对中没有元素,那么它左边(或右边)没有比它矮的,最矮的就记为它自己。
3.
关于统计答案,不能只统计两边最小。这样漏掉了以该点向上的高度为最小值(答案的高)的答案。
所以要:
4.
假如第i行第r个点向前最长的等差数列到位置l,这算一个区间,那么下一个区间的r不能从l−1开始,而要从l开始。
5.
奇怪的算法还是不要写了,悬线法好哇!
但还不知道为啥错。
(work和work1类似)
6.
选出一段等差数列的区间后,再从中选公差为等差数列的区间时,必须在先选出的等差数列的区间内。
因为循环结束后会j−−,所以j要开大一个。但如果不特判r==x时,可能会陷入一直是x到x区间的死循环。
终极版代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1005;
int n,m,a[N][N],up[N][N],gc[N][N];
int l1,r1,l2,r2,l,r,ans,lef[N][N],lefg[N][N];
struct node{
int val,id;
}q1[N],q2[N],tmpz[N],tmpy[N];
void work(int t,int x,int y)
{
l1=l2=1; r1=r2=0;
for(int i=x;i<=y;i++)
{
while(r1&&q1[r1].val>=up[t][i]) --r1;
if(r1<=0) tmpz[i].val=up[t][i],tmpz[i].id=x;
else tmpz[i].val=q1[r1].val,tmpz[i].id=q1[r1].id;
q1[++r1].val=up[t][i]; q1[r1].id=i;
}
for(int i=y;i>=x;i--)
{
while(r2&&q2[r2].val>=up[t][i]) --r2;
if(r2<=0) tmpy[i].val=up[t][i],tmpy[i].id=y;
else tmpy[i].val=q2[r2].val,tmpy[i].id=q2[r2].id;
q2[++r2].val=up[t][i]; q2[r2].id=i;
}
for(int i=x;i<=y;i++)
{
int xt=min(tmpy[i].val,tmpz[i].val)*(tmpy[i].id-tmpz[i].id+1);
int yt=up[t][i]*(tmpy[i].id-tmpz[i].id-1);
int xxt=tmpy[i].val*(tmpy[i].id-tmpz[i].id);
int yyt=tmpz[i].val*(tmpy[i].id-tmpz[i].id);
ans=max(ans,max(xt,yt));
ans=max(ans,max(xxt,yyt));
}
return ;
}
/*void work1(int t,int x,int y)
{
l=x; r=x+1;
while(l<=y&&r<=y)
{
int ch=gc[t][r]-gc[t][l];
while(gc[t][r]-gc[t][r-1]==ch&&r<=y+1) ++r;
--r;
work(t,l,r);
l=r; r=l+1;
}
}*/
void work1(int t,int x,int y)
{
int r;
for(int j=y;j>=x;j--)
{
r=j+1-lefg[t][j];
work(t,max(r,x),max(x,j));
if(r!=x) j=r+1; //
else j=r; //
}
}
int main()
{
// freopen("rect.in","r",stdin);
// freopen("rect.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
gc[i][j]=a[i-1][j]-a[i][j];
if(i>1) up[i][j]=2;
else up[i][j]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(gc[i][j]==gc[i-1][j])
up[i][j]=up[i-1][j]+1;
}
for(int i=1;i<=n;i++)
{
lef[i][1]=1; lef[i][2]=2;
for(int j=3;j<=m;j++)
{
if(a[i][j]-a[i][j-1]==a[i][j-1]-a[i][j-2])
lef[i][j]=lef[i][j-1]+1;
else lef[i][j]=2;
}
}
for(int i=1;i<=n;i++)
{
lefg[i][1]=1; lefg[i][2]=2;
for(int j=3;j<=m;j++)
{
if(gc[i][j]-gc[i][j-1]==gc[i][j-1]-gc[i][j-2])
lefg[i][j]=lefg[i][j-1]+1;
else lefg[i][j]=2;
}
}
/* for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cout<<lefg[i][j]<<"*";
if(j==m) cout<<endl;
}*/
for(int i=1;i<=n;i++)
{
int r;
for(int j=m;j>=1;j--)
{
r=j+1-lef[i][j];
work1(i,r,j);
if(r!=1) j=r+1; //
else j=r; //
}
}
/* for(int i=1;i<=n;i++)
{
l=1;r=2;
while(l<=m&&r<=m)
{
int ch=a[i][r]-a[i][l];
while(a[i][r]-a[i][r-1]==ch&&r<=m+1) ++r;
--r;
work1(i,l,r);
l=r; r=l+1;
}
}*/
printf("%d\n",ans);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用