P5858 「SWTR-03」Golden Sword做题笔记
开始看的时候以为是个背包,看了一眼标签,发现没有背包两个字,觉得可能是漏加上去了,但背包死活想不出思路,看了眼题解,原来是 \(dp\) 加单调队列优化,然后开始看题解,看了大半天没看懂,照着题解的框架打了一遍才半懂,大致思路是用单调队列维护炉子里的和还没进炉子里的原料的顺序?然后发现照着题解打的 \(35pts\),找了半天才发现是最小值的初始化问题,题解里用的是 -1008600110086001
,而我用的是 -0x7fffffffffffffff
。后来找了某大佬,说我用的数太小容易溢出,并推荐我用 -0x3f3f3f3f3f3f3f3f
,然后就过了。
#include <bits/stdc++.h>
using namespace std;
const long long FINF=-0x3f3f3f3f3f3f3f3f;
long long n,m,k,a,s[5005][5005],q[5005],t[5005],ans,l,r,i,j;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>k;
for (i=0;i<=n;i++)
{
for (j=0;j<=m;j++)
{
s[i][j]=FINF;
}
}
s[0][0]=0;
for (i=1;i<=n;i++)
{
cin>>a;
l=1;
r=1;
t[l]=m;
q[l]=s[i-1][m];
for (j=m;j>0;j--)
{
while (t[l]>j+k-1 && l<=r) l++;
while (q[r]<s[i-1][j-1] && l<=r) r--;
t[++r]=j-1;
q[r]=s[i-1][j-1];
s[i][j]=q[l]+j*a;
}
}
ans=FINF;
for (i=0;i<=m;i++)
{
ans=max(ans,s[n][i]);
}
cout<<ans<<endl;
return 0;
}