2 条题解

  • 0
    @ 2025-11-8 21:05:10

    这道题不难想到,最终的答案肯定是一个区间和,由于我们要在保证软件ACM成员都开心的情况的条件下,保证自己的最多,那既然最多,其他成员的美味值就恰好为v,或者第一次大于v的时候就停止分,这样确保lfq分到的是最多的,我们可以分为三个区间,lfq分在[L,R]中的蛋糕,那剩余的[1,L-1],[R+1,n]的值的和要>=m,于是就有下面的代码
    #include <bits/stdc++.h>
    using namespace std;
    long long a[200100], l[200100], r[200100], he[200100];
    int main()
    {
    int t;
    scanf("%d", &t);
    for (int i = 1; i <= t; i++)
    {
    int n, m, v;
    scanf("%d%d%d", &n, &m, &v);
    for (int i = 1; i <= n; i++)
    {
    scanf("%lld", &a[i]);
    }
    l[0] = 0;
    long long sum = 0;
    for (int i = 1; i <= n; i++)//该代码是求从1到n,满足美味值大于v的人数,例如,此时l[i]的值为3,那就代表从1到i有3个人满足分到蛋糕的美味值大于v
    {
    l[i] = l[i - 1];
    sum += a[i];
    if (sum >= v)
    {
    l[i]++;
    sum = 0;
    }
    }
    sum = 0;
    r[n + 1] = 0;
    for (int i = n; i >= 1; i--)//与l代表的意义一样,之所以从n到1,是因为最终的答案肯定是一个区间和,假如是[L,R],那整个n就被分为三部分[1,L-1],[L,R],[R+1,n],由于不清楚R+1,所以我们没法从R+1到n,但是我们可以从n到R+1,那为什么不直接用之前的l数组呢?那是因为他们两个中间隔着[L,R],而l数组记录了[L,R],会对之后的数据产生影响
    {
    r[i] = r[i + 1];
    sum += a[i];
    if (sum >= v)
    {
    r[i]++;
    sum = 0;
    }
    }
    he[0] = 0;//前缀和,用于计算最终答案。
    for (int i = 1; i <= n; i++)
    {
    he[i] = he[i - 1] + a[i];
    }
    long long ans = -1;
    if (l[n] >= m)//因为从1到n,美味值至少为v的人数达到m,所以最终答案的值不为-1。
    {
    ans = 0;
    }
    int r1 = 1;//开始遍历区间[L,R],这种方法叫双指针,可以去学一学,先固定右端点r1,移动左端点l1,当左端点大于右端点时,我们把此时的右端点移到左端点。
    int l1 = 1;
    for (l1 = 1; l1 <= n; l1++)
    {
    if (l1 > r1)
    {
    r1 = l1;
    }
    while (l[l1 - 1] + r[r1 + 1] >= m && r1 <= n)//前提条件成立,开始求最大值(通过移动右端点),直到前提条件不符合。
    {
    ans = max(ans, he[r1] - he[l1 - 1]);
    r1++;
    }
    }
    printf("%lld\n", ans);
    }
    return 0;
    }

    信息

    ID
    1188
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    递交数
    19
    已通过
    2
    上传者