有 n 个人从左到右的排队,对应的身高的为 Hi, 先在你可以将这个队伍分成若干个连续 group, 且每个 group 中的人数不能超过 L,要求从第二组开始每组的最后一个人的高度比前一组的最后一个人的高度高,第 i 组最后一个人的高度为 bi,那么分组总分数和为: 求一个合理的分组方案,让分组分数最大。
思路
这题我们假设 dp [i] 表示前 i 个人分组的最大得分,我们对每个 i 位置多考虑 dp [i] , 当我们一直考虑到 dp [n] 的时候就得到的答案了,
当 n 的数据范围较小的时候,我们考虑 dp [i] 可以从 i 位置前面的 L 个人进行 for 循环暴力转移。
这题 n 的范围是 1e5 不能进行暴力转移,因为每次转移只能从比 i 这个人低的进行转移,我们考虑对对身高进行结构体排序,用线段树按身高从小到大维护每个位置的 dp 值,这样身高大的就不会影响当前正在维护的 dp 值,在用 线段树维护区间最大值就可以 log (n) 进行状态转移了。
代码
#include<bits/stdc++.h>
using namespace std;#define db double#define ll long long#define sc scanf#define pr printf#define fi first#define se second#define pb push_back#define m_p make_pair#define Pir pair<ll, ll>#define inf 0x3f3f3f3f#define INF 0x3f3f3f3f3f3f3f3f/*==========ACMer===========*/#define int ll#define ls(rot) (rot << 1) #define rs(rot) (rot << 1 | 1) constint N =1e5+10;int n, m;
ll dp[N];struct Data
{
ll val, pos;
bool operator <(const Data x)const{if(val == x.val)return pos > x.pos;return val < x.val;}} d[N];struct Tree
{
ll val;int l, r;} t[N <<2];voidpush_up(int k){
t[k].val =max(t[ls(k)].val, t[rs(k)].val);}voidbuild(int k,int l,int r){
t[k].l = l, t[k].r = r;if(l == r){
t[k].val =-INF;return;}int md =(l + r)>>1;build(ls(k), l, md);build(rs(k), md +1, r);push_up(k);}voidupdate(int k,int x, ll y){if(t[k].l > x || t[k].r < x)return;if(t[k].l >= x && t[k].r <= x){
t[k].val = y;return;}update(ls(k), x, y);update(rs(k), x, y);push_up(k);}
ll query(int k,int l,int r){if(t[k].l > r || t[k].r < l)return-INF;if(t[k].l >= l && t[k].r <= r){return t[k].val;}returnmax(query(ls(k), l, r),query(rs(k), l, r));}signedmain(){int T, cas =1;sc("%lld",&T);while(T --){sc("%lld %lld",&n,&m);for(int i =1; i <= n; i ++){int x;sc("%lld",&x);
d[i]=(Data){ x, i };}sort(d +1, d +1+ n);build(1,1, n);for(int i =1; i <= n; i ++){
dp[d[i].pos]=-INF;if(d[i].pos <= m){
dp[d[i].pos]= d[i].val * d[i].val;}
ll x =query(1,max(1LL, d[i].pos - m), d[i].pos -1);if(x !=-INF)
dp[d[i].pos]=max(dp[d[i].pos], x + d[i].val * d[i].val);if(dp[d[i].pos]!=-INF)update(1, d[i].pos, dp[d[i].pos]- d[i].val);}pr("Case #%lld: ", cas ++);if(dp[n]!=-INF)pr("%lld\n", dp[n]);elsepr("No solution\n");}/* return 0; */}
题意有 n 个人从左到右的排队,对应的身高的为 Hi, 先在你可以将这个队伍分成若干个连续 group, 且每个 group 中的人数不能超过 L,要求从第二组开始每组的最后一个人的高度比前一组的最后一个人的高度高,第 i 组最后一个人的高度为 bi,那么分组总分数和为:求一个合理的分组方案,让分组分数最大。思路这题我们假设 dp [i] 表示前 i 个人分组的最大得分,我们对每个 i 位置多考虑 dp [i] , 当我们一直考虑到 dp [n] 的时候就得到的答案了,当 n 的数据范围较小