LOJ3215 「PA 2019」Muzyka pop

题目

如果\(m\)\(2^w-1\)的形式,那么我们可以搞一个非常厉害的区间dp,设\(dp_{w,l,r}\)表示当\(m=2^w-1\)时,\([l,r]\)的最大贡献是多少,我们枚举\(i\),让\([l,i]\)的最高位填\(0\)\([i+1,r]\)的最高位填\(1\),在这里直接算一下贡献,到下一层计算即可

处理出上面那个东西之后,按照数位dp的方式来对着m卡位就好了

代码

#include<bits/stdc++.h>
#define re register
#define LL long long
int n;LL m,a[205],pre[205];
LL dp[65][205][205],g[65][205][205];
int u[65][205][205],vis[65][205][205];
const LL inf=-1e17;
LL Dfs(int dep,int l,int r) {
	if(l>r) return 0;if(!dep) return l==r?0:inf;
	if(r-l+1>(1ll<<dep)) return inf;
	if(vis[dep][l][r]) return dp[dep][l][r];
	vis[dep][l][r]=1;LL nw=inf;
	for(re int i=l-1;i<=r;++i) {
		LL x=Dfs(dep-1,l,i)+Dfs(dep-1,i+1,r)+pre[r]-pre[i];
		if(x>nw) nw=x;
	}
	return dp[dep][l][r]=nw;
}
LL Getans(int dep,int l,int r) {
	if(l>r) return 0;if(!dep) return l==r?0:inf;
	if(u[dep][l][r]) return g[dep][l][r];
	LL nw=inf;u[dep][l][r]=1;
	if(m>>(dep-1)&1) {
		for(re int i=l-1;i<=r;++i)  {
			LL x=Dfs(dep-1,l,i)+Getans(dep-1,i+1,r)+pre[r]-pre[i];
			if(x>nw) nw=x;
		}
		return g[dep][l][r]=nw;
	}
	return g[dep][l][r]=Getans(dep-1,l,r);
}
int main() {
	scanf("%d%lld",&n,&m);
	for(re int i=1;i<=n;i++)scanf("%lld",&a[i]),pre[i]=pre[i-1]+a[i];
	LL S=m;int dep=0;while(S) dep++,S>>=1ll;
	printf("%lld\n",Getans(dep,1,n));return 0;
}
posted @ 2019-12-26 17:48  asuldb  阅读(393)  评论(0)    收藏  举报