打卡信奥刷题(3195)用C++实现信奥题 P8102 「LCOI2022」 Cow Insertion
P8102 「LCOI2022」 Cow Insertion
题目背景
Farmer John 迎来了新奶牛——Bessie。每个奶牛都会有一定的开心值,Farmer John 希望 Bessie 能更幸福的生活在这里。
题目描述
牛棚里原来有 nnn 头奶牛,开心值的感染距离 mmm,并且 aia_iai 表示原来牛棚中第 i(1≤i≤n)i(1\le i\le n)i(1≤i≤n) 头牛的开心值。并且,Bessie 同样拥有一个开心值 AAA。
整个牛棚的开心值是 ∑i=1n−m+1 maxi≤j≤i+m−1 aj\sum\limits_{i=1}^{n-m+1}\ \max\limits_{i\le j\le i+m-1}\ a_ji=1∑n−m+1 i≤j≤i+m−1max aj,Bessie 可以住在任意两头牛的中间或起始以及最后。Farmer John 想知道:Bessie 来这里之后,整个牛棚的开心值最大为多少。
输入格式
第一行包含三个整数 n,m,An,m,An,m,A。分别表示为奶牛个数,开心值的感染距离,以及 Bessie 的开心值。
接下来一行,包含 nnn 个数 aia_iai,表示原来牛棚中第 i(1≤i≤n)i(1\le i\le n)i(1≤i≤n) 头牛的开心值。
输出格式
仅一行,表示 Bessie 来这里之后,整个牛棚的开心值的最大值。
输入输出样例 #1
输入 #1
3 2 50
60 100 70
输出 #1
270
说明/提示
【样例解释】
- 当 Bessie 在第一个位置时(50,60,100,7050,60,100,7050,60,100,70),整个牛棚的开心值的最大值为 max{60,50}+max{60,100}+max{100,70}\newcommand{\cases}[1]{\{#1\}}\max\cases{60,50}+\max\cases{60,100}+\max\cases{100,70}max{60,50}+max{60,100}+max{100,70},即 60+100+100=26060+100+100=26060+100+100=260。
- 当 Bessie 在第二个位置时(60,50,100,7060,50,100,7060,50,100,70),整个牛棚的开心值的最大值为 max{60,50}+max{50,100}+max{100,70}\newcommand{\cases}[1]{\{#1\}}\max\cases{60,50}+\max\cases{50,100}+\max\cases{100,70}max{60,50}+max{50,100}+max{100,70},即 60+100+100=26060+100+100=26060+100+100=260。
- 当 Bessie 在第三个位置时(60,100,50,7060,100,50,7060,100,50,70),整个牛棚的开心值的最大值为 max{60,100}+max{100,50}+max{50,70}\newcommand{\cases}[1]{\{#1\}}\max\cases{60,100}+\max\cases{100,50}+\max\cases{50,70}max{60,100}+max{100,50}+max{50,70},即 100+100+70=270100+100+70=270100+100+70=270。
- 当 Bessie 在第四个位置时(60,100,70,5060,100,70,5060,100,70,50),整个牛棚的开心值的最大值为 max{60,100}+max{100,70}+max{70,50}\newcommand{\cases}[1]{\{#1\}}\max\cases{60,100}+\max\cases{100,70}+\max\cases{70,50}max{60,100}+max{100,70}+max{70,50},即 70+100+100=27070+100+100=27070+100+100=270。
显然,整个牛棚的开心值的最大值为 max{260,260,270,270}=270\newcommand{\cases}[1]{\{#1\}}\max\cases{260,260,270,270}=270max{260,260,270,270}=270。
【数据范围与约定】
| subtask | n≤n\len≤ | 分值 |
|---|---|---|
| 111 | 5×1025\times10^25×102 | 101010 |
| 222 | 5×1035\times10^35×103 | 202020 |
| 333 | 5×1065\times10^65×106 | 707070 |
对于 100%100\%100% 的数据,1≤m≤n1\le m\le n1≤m≤n,0≤ai,A≤1000\le a_i, A\le1000≤ai,A≤100。
C++实现
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
long long f[5000010], a[5000010], g[5000010];
int q[5000010], st = 1, ed;
int main()
{
int n, m;
long long A;
scanf("%d%d%lld", &n, &m, &A);
long long sum = A;
for (int i = 1; i <= n; i++)
{
scanf("%lld", a + i);
sum += a[i];
if (st <= ed && i - q[st] >= m - 1) st++;
while (st <= ed && a[q[ed]] < a[i]) ed--;
q[++ed] = i;
if (i >= m - 1) f[i] = a[q[st]];
} // 单调队列求 f 数组
if (m == 1)
{
printf("%lld\n", sum);
return 0;
} // 特判
st = 1, ed = 0;
for (int i = 1; i <= n; i++)
{
if (st <= ed && i - q[st] >= m) st++;
while (st <= ed && a[q[ed]] < a[i]) ed--;
q[++ed] = i;
if (i >= m) g[i] = a[q[st]];
} // 清空队列,不另外开新数组,节省空间
for (int i = m + 1; i <= n; i++) g[i] += g[i - 1];
for (int i = m; i <= n; i++)
f[i] = max(A, f[i]) + f[i - 1];
long long ans = 0;
for (int i = 0; i <= n; i++)
ans = max(ans, g[max(i - m + 1, 0)] + g[n] - g[i] + f[i] - f[max(i - m, 0)]);
printf("%lld\n", ans);
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐
所有评论(0)