2019 GDUT Rating Contest #I B. Teamwork
题目见 :
http://codeforces.com/group/NVaJtLaLjS/contest/238166/problem/B
题目大意:
n个数,可以把相邻的分成k组,每组所有数变成其中最大的,求最大总和。
思路:
一道dp,用dp[i]表示前i个数分组能够得到的最大和,那么对于j=1~i-1, dp[i]=max(dp[i],dp[j-1]+(i-j+1)*maxim(j,i)),maxim表示第j到第i个数中最大值。
一次优化:
比赛时我的代码使用st表求得maxim的值。
二次优化:
经过同学讨论和师兄分析,发现可以不用st表,使用倒序储存即可,我比赛时打的st亏大了,呜呜呜》》》》》》》
实现:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int st[16][10108];
int er[16];
int maxim(int x,int y)
{
int t=int(log(double(y-x+1))/log(double(2)));
return max(st[t][x],st[t][y-er[t]+1]);
}
int main()
{
int i,j,n,k;
int f[10010];
int dp[10010];
scanf("%d %d",&n,&k);
for (i=1;i<=n;i++)
scanf("%d",&f[i]);
er[0]=1;
for (i=1;i<=15;i++)
er[i]=er[i-1]*2;
for (i=1;i<=n;i++)
st[0][i]=f[i];
for (i=1;i<=int(log(double(n))/log(double(2)))+1;i++)
for (j=1;j<=n;j++)
if (j+er[i]-1<=n) st[i][j]=max(st[i-1][j],st[i-1][j+er[i-1]]);
for (i=0;i<=10000;i++) dp[i]=0;
dp[1]=f[1];
for (i=2;i<=n;i++)
for (j=i;j>=max(1,i-k+1);j--)
{
dp[i]=max(dp[i],dp[j-1]+(i-j+1)*maxim(j,i));
}
printf("%d\n",dp[n]);
return 0;
}