题目地址
设
表示放入前
个物品且锅中还有
个物品所获得的最大耐久度。
很容易推出
{
}+
时即为不拿出来任何一个物品,
时表示拿出
个物品,
是为了给第
个物品留个位置。
如果打三重的
语句的话,时间复杂度为
,咕咕咕。
然而
{
}这个式子珂以用单调队列优化啊!
相当于移动区间,求每个
区间中的最大值。 珂以通过
计算出
的所有值。
时间复杂度
,能过。
:
# include <bits/stdc++.h>
using namespace std;
// const
const int N=5505;
const long long inf=103492948382342342;
//move int
int n,w,s;
long long dp[N][N];
long long a[N];
int front,rear;
struct node
{
long long _time;
long long x;
//node(int _timer,long long _x){_time=_timer,x=_x;}
};
node q[N+10];
inline long long read(void)
{
long long s=0;
int w=1;
char ch=getchar() ;
while(!isdigit(ch))
{
if(ch=='-') w=-1;
ch=getchar() ;
}
while(isdigit(ch))
{
s=s*10+ch-'0';
ch=getchar() ;
}
return s*w;
}
void Input(void)
{
n=read(),w=read(),s=read() ;
for(int i=1;i<=n;i++)
{
a[i]=read() ;
}
return;
}
void solve(void)
{
for(int i=0;i<=n;i++)
{
for(int j=0;j<=w;j++)
{
dp[i][j]=-inf;
}
}
dp[0][0]=0;
//compare
for(int i=1;i<=n;i++)
{
for(int k=1;k<=10;k++) q[k].x=q[k]._time=0;
front=rear=0;
q[++rear].x=dp[i-1][w];
q[rear]._time=w;
for(int j=w;j>=1;j--)
{
while(q[front+1]._time>j+s-1&&front<rear)
{
front++;
}
while(q[rear].x<=dp[i-1][j-1]&&front<rear)
{
rear--;
}
rear++;
q[rear].x=dp[i-1][j-1];
q[rear]._time=j-1;
dp[i][j]=q[front+1].x+a[i]*j;
}
}
long long ans=-inf;
for(int i=0;i<=w;i++)
{
ans=max(ans,dp[n][i]) ;
}
cout<<ans<<endl ;
}
int main(void)
{
Input() ;
solve() ;
return 0;
}