牛客提高D4t2 卖羊驼
分析
不难想到dp[i][j]表示前i个数分了j组的最大值
我们发现这个dp状态有决策单调性
g[i][j]表示对于第i个数它的第j位最近出现的位置
每次一定从这些点转移
预处理即可
似乎还可以做到1e5
https://www.cnblogs.com/hanyuweining/p/10321914.html
就是这个/kel
等有时间再看?
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
#define max(x,y) (x>y?x:y)
int dp[5010][1010],g[5010][32],pre[5010][32],n,m,f[32],a[5010],sum[32];
signed main(){
int i,j,k;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld",&a[i]);
for(i=1;i<=n;i++){
for(j=0;j<=31;j++)
if((1ll<<j)&a[i])f[j]=i,sum[j]=a[i];
else sum[j]|=a[i];
for(j=0;j<=31;j++)
g[i][j]=f[j],pre[i][j]=sum[j];
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
for(k=0;k<=31;k++)
dp[i][j]=max(dp[i][j],dp[max(0,g[i][k]-1)][j-1]+pre[i][k]);
cout<<dp[n][m]<<"\n";
return 0;
}