牛客提高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;
}
posted @ 2019-08-24 19:37  水题收割者  阅读(141)  评论(0编辑  收藏  举报