dp学习笔记之P5124 Teamwork G

这是写给我自己看的,以便复习。

[题目描述]

在 Farmer John 最喜欢的节日里,他想要给他的朋友们赠送一些礼物。由于他并不擅长包装礼物,他想要获得他的奶牛们的帮助。你可能能够想到,奶牛们本身也不是很擅长包装礼物,而 Farmer John 即将得到这一教训。Farmer John 的 N 头奶牛\((1≤N≤10 ^4)\)排成一行,方便起见依次编号为 1…N。奶牛 i 的包装礼物的技能水平为\(s_i\)。她们的技能水平可能参差不齐,所以 FJ 决定把她的奶牛们分成小组。每一组可以包含任意不超过 K 头的连续的奶牛\((1≤K≤10^3)\)。并且一头奶牛不能属于多于一个小组。由于奶牛们会互相学习,这一组中每一头奶牛的技能水平会变成这一组中水平最高的奶牛的技能水平。

请帮助 FJ 求出,在他合理地安排分组的情况下,可以达到的技能水平之和的最大值。

[题目解答]

点击查看解答 很显然这是一道线性dp题目,由于是区间最大值,我们就用st表(多写写,上了考场自有用处)。

状态转移不难想,设\(f_i\)为前i个奶牛的最大技能水平,由此可知

\(f_i=max(f_i,f_{i-j}+getv(i-j+1,i))\)

接下来撸代码就行了awa

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rgi register int
#define DEBUG(x) printf("%s ",x);
#define fastio cin.tie(nullptr)->ios::sync_with_stdio(false);
#define inf (1<<31)
#define awa {return 0;}
#define N 10010
using namespace std;

int n,k,a[N],dp[N],st[N][31],logn[100010];

void init(){
	logn[1]=0,logn[2]=1;
	for(rgi i=3;i<=100000;i++){
		logn[i]=logn[i>>1]+1;
	}
}

inline int getv(int l,int r){
	int k=logn[r-l+1];
	return max(st[l][k],st[r-(1<<k)+1][k]);
}

int main(){
	fastio;
	cin>>n>>k;
	init();
	for(rgi i=1;i<=n;i++){
		cin>>a[i];
		st[i][0]=a[i];
	}
	for(rgi j=1;j<=logn[n];j++){
		for(rgi i=1;i+(1<<j)-1<=n;i++){
			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
	for(rgi i=1;i<=n;i++){
		for(rgi j=1;j<=k;j++){
			if(j>i)break;
//			DEBUG("CHK");
			dp[i]=max(dp[i],dp[i-j]+getv(i-j+1,i)*j);
		}
	}
	printf("%d",dp[n]);
	awa;
}
posted @ 2025-08-22 22:27  epicbook  阅读(6)  评论(0)    收藏  举报