欢迎光临
我们一直在努力

小苯的能量项链【牛客tracker & 每日一题】

小苯的能量项链

时间限制:1秒 空间限制:256M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多! 在这里插入图片描述

题目描述

小苯有一个含有

n

n

n 颗珠子的“能量项链”,珠子排成一排,其中第

i

i

i 颗珠子的能量为

a

i

a_i

ai

但是这个项链并不稳定,如果项链的珠子个数不少于 3 个,则它即将发生“崩坏”,即:除了第一颗珠子和最后一颗珠子以外的其余所有珠子都将销毁,最终只留下第一颗和最后一颗珠子。

小苯现在希望项链在“崩坏”后保留尽可能多的能量,为此他可以在崩坏前执行以下的操作:

  • 去掉项链的第一颗珠子(也就意味着项链原本的第二颗珠子将会变成第一颗)。
  • 去掉项链的最后一颗珠子(也就意味着项链原本的倒数第二颗珠子将会变成最后一颗)。

两种操作各自均需要花费 1 秒时间,而现在距离项链发生“崩坏”仅剩

k

k

k 秒,小苯想知道,他最多可以保留住多少能量,请你帮他算一算吧。

输入描述

每个测试文件内都包含多组测试数据。

第一行一个正整数

T

 

(

1

T

1000

)

T\\ (1 \\le T \\le 1000)

T (1T1000),表示测试数据的组数。

接下来对于每组测试数据,输入包含两行。

第一行两个整数

n

,

k

 

(

1

n

5

×

10

5

,

0

k

10

9

)

n,k\\ (1 \\le n \\le 5 \\times 10^5,0 \\le k \\le 10^9)

n,k (1n5×105,0k109),表示项链的珠子个数和距离项链“崩坏”的时间。

第二行

n

n

n 个正整数

a

i

 

(

1

a

i

10

9

)

a_i\\ (1 \\le a_i \\le 10^9)

ai (1ai109),表示每颗珠子的能量。

(保证所有测试数据中

n

n

n 的总和不超过

5

×

10

5

5 \\times 10^5

5×105。)

输出描述

对于每组测试数据,输出一行一个整数表示小苯能保留的最大能量。

示例1

输入:

2
5 2
2 3 4 5 2
1 1
114514

输出:

8
114514

说明: 对于第一组测试数据,距离发生“崩坏”还有

k

=

2

k=2

k=2 秒,最优的方案是删除目前的第一个和最后一个数字,那么项链的能量会变成

{

3

,

4

,

5

}

\\{3,4,5\\}

{3,4,5},最终

3

3

3

5

5

5 会保留下来,因此最大值为

8

8

8

对于第二组测试数据,由于项链珠子个数小于3,因此不会发生崩坏,最终保留的能量就是

114514

114514

114514

解题思路

本题是贪心 + 滑动窗口维护前缀最大值的经典题型。需要在最多

k

k

k 次删除头/尾操作后,使得最终(可能崩坏后)保留的能量最大。由于崩坏只保留首尾两个珠子(若剩余珠子数

3

\\ge 3

3),或者剩余珠子数

<

3

<3

<3 时直接保留全部,问题可以转化为选择两个位置

l

r

l \\le r

lr 作为最终保留的首尾,满足操作次数限制,并最大化

v

l

+

v

r

v_l + v_r

vl+vr

1. 问题等价转化
  • 若初始珠子数

    n

    <

    3

    n < 3

    n<3,不会崩坏,答案就是所有珠子能量之和。

  • n

    3

    n \\ge 3

    n3,我们通过若干次删除头部和尾部的操作,将原序列缩短为一个新的序列。新序列的首尾珠子在原序列中的下标为

    l

    l

    l

    r

    r

    r,且满足:

    • 删除操作次数为

      (

      l

      1

      )

      +

      (

      n

      r

      )

      k

      (l-1) + (n-r) \\le k

      (l1)+(nr)k

    • 最终序列长度为

      r

      l

      +

      1

      r-l+1

      rl+1,可能

      3

      \\ge 3

      3(发生崩坏,保留

      v

      l

      +

      v

      r

      v_l+v_r

      vl+vr),也可能

      =

      2

      =2

      =2(不崩坏,同样保留

      v

      l

      +

      v

      r

      v_l+v_r

      vl+vr)。无论哪种情况,我们关心的都是

      v

      l

      +

      v

      r

      v_l+v_r

      vl+vr

  • 目标:在满足

    (

    l

    1

    )

    +

    (

    n

    r

    )

    k

    (l-1)+(n-r) \\le k

    (l1)+(nr)k

    l

    <

    r

    l < r

    l<r 的条件下,最大化

    v

    l

    +

    v

    r

    v_l + v_r

    vl+vr

2. 算法设计
  • d

    i

    f

    =

    max

    (

    2

    ,

     

    n

    k

    )

    dif = \\max(2,\\ n-k)

    dif=max(2, nk)。直观上,最多删除

    k

    k

    k 个珠子后,剩余珠子数至少为

    n

    k

    n-k

    nk;但若

    n

    k

    2

    n-k \\le 2

    nk2,则我们至少可以留下

    2

    2

    2 个珠子(避免崩坏),所以

    d

    i

    f

    dif

    dif

    2

    2

    2 保证至少两个珠子。

  • 对于固定的右端点

    r

    r

    r,允许的左端点

    l

    l

    l 必须满足:

    (

    l

    1

    )

    +

    (

    n

    r

    )

    k

    l

    r

    d

    i

    f

    +

    1

    (l-1)+(n-r) \\le k \\quad\\Rightarrow\\quad l \\le r – dif + 1

    (l1)+(nr)klrdif+1 其中

    d

    i

    f

    =

    max

    (

    2

    ,

     

    n

    k

    )

    dif = \\max(2,\\ n-k)

    dif=max(2, nk)

  • 因此,对于每个

    r

    r

    r

    d

    i

    f

    dif

    dif

    n

    n

    n,合法的

    l

    l

    l 取值范围是

    [

    1

    ,

     

    r

    d

    i

    f

    +

    1

    ]

    [1,\\ r-dif+1]

    [1, rdif+1]。我们需要在该前缀中找到最大的

    v

    l

    v_l

    vl,然后计算

    v

    r

    +

    max

    1

    l

    r

    d

    i

    f

    +

    1

    v

    l

    v_r + \\max_{1\\le l\\le r-dif+1} v_l

    vr+max1lrdif+1vl 更新答案。

  • 实现时,维护一个变量 mx 表示当前前缀

    1

    1

    1

    i

    d

    i

    f

    +

    1

    i-dif+1

    idif+1 的最大值。随着

    r

    r

    r 右移,前缀右端点也在右移,可以动态更新 mx。

3. 复杂度分析
  • 时间复杂度:每组数据只需线性扫描一遍数组,

    O

    (

    n

    )

    O(n)

    O(n)。所有测试数据的

    n

    n

    n 之和不超过

    5

    ×

    10

    5

    5\\times 10^5

    5×105,总时间可行。

  • 空间复杂度:仅需存储数组和几个变量,

    O

    (

    n

    )

    O(n)

    O(n)

总结

将操作后的首尾保留问题转化为选择满足约束的两个位置,通过固定右端点并维护左侧前缀最大值,在线性时间内求出最大能量和。dif 的设置巧妙涵盖了剩余珠子数为

2

2

2(不崩坏)和

3

\\ge 3

3(崩坏)两种情况,使算法统一简洁。

代码内容

#include <bits/stdc++.h>
using namespace std;

#define endl '\\n'
typedef long long ll;
typedef unsigned long long ull;
typedef vector<vector<ll>> vvt;
typedef pair<ll,ll> pll;
const ll N=1e3+10;
const ll INF=1e18;
const ll M=1e6+10;
const ll mod=998244353;

using i128=__int128_t;

void solve()
{
ll n,k;
cin>>n>>k;
vector<ll> v(n+1);
for(ll i=1;i<=n;i++) cin>>v[i];
if(n<3)
{
ll ans=0;
for(ll i=1;i<=n;i++) ans+=v[i];
cout<<ans<<'\\n';
return;
}
ll dif=max(2LL,nk);
ll mx=0;
ll ans=0;
for(ll i=dif;i<=n;i++)
{
mx=max(mx,v[idif+1]);
ans=max(ans,mx+v[i]);
}
cout<<ans<<'\\n';
}

int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
ll t;
cin>>t;
while(t) solve();
return 0;
}

赞(0)
未经允许不得转载:171主机测评 » 小苯的能量项链【牛客tracker & 每日一题】
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址