题解:P3800 Power收集
一眼 DP,设
即每次从上一行可行的位置向下转移(
直接计算的时间复杂度
观察上式所求
对于每一行,对其上一行建 ST 表。更新坐标
时间复杂度
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=4005;
int n,m,k,t;
int st[N][15],f[N][N];
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&t);
for(int i=1;i<=k;i++)
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
f[x][y]=v;
}
int tp=__lg(m),ans=0; //__lg()函数用于计算以2为底的对数
for(int i=2;i<=n;i++) //从第二行开始计算,因为第一行可以从任意位置开始
{
for(int j=1;j<=m;j++)
st[j][0]=f[i-1][j];
for(int l=1;l<=tp;l++) //建立ST表
for(int x=1;x+(1<<l)-1<=m;x++)
st[x][l]=max(st[x][l-1],st[x+(1<<(l-1))][l-1]);
for(int j=1;j<=m;j++)
{
auto query = [&](int l,int r) -> int //lambda函数写法,可以直接当正常函数用
{
int p=__lg(r-l+1);
return max(st[l][p],st[r-(1<<p)+1][p]);
};
f[i][j]+=query(max(j-t,1),min(m,j+t)); //对范围取max/min防止查询越界
ans=max(ans,f[i][j]);
}
}
printf("%d\n",ans);
return 0;
}
AC 记录