专栏文章
题解:P11963 [GESP202503 六级] 环线
P11963题解参与者 3已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @miptwzh1
- 此快照首次捕获于
- 2025/12/03 17:53 3 个月前
- 此快照最后确认于
- 2025/12/03 17:53 3 个月前
begin
前言(渺小)
考试的时候打了一个超级无敌大歪解,个人认为漏洞百出,但是还是成功的骗到了 的分数。(大概是数据的锅。?)
考后看到标签后恍然大悟,造就了这篇题解。
另:不会单调队列的可以去看看 P1886 滑动窗口 /【模板】单调队列。
思路
我们简化一下题目:截取一个长度 的序列,使它的和最大。
那么众所周知,如果要让和最大,那么减掉的就越少越好。
所以我们可以先求出破环成链后的 数组的前缀和 数组,然后对于每一个 在确保长度不超过 的情况下,减掉一个最小的前缀和,最后取最大值即可。
针对上述思路,单调队列简直再合适不过了。
Code
CPP#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N=4e5+10;
ll n,a[N],sum[N],q[N],head=1,tail,ans=-1e10;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
// 破环成链
for (ll i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
// 前缀和
for (ll i=1;i<=n*2;i++) sum[i]=sum[i-1]+a[i];
// 单调队列
for (ll i=1;i<=n*2;i++)
{
while (head<=tail && i-q[head]>n) head++; // 确保区间长度合法
while (head<=tail && sum[q[tail]]>=sum[i]) tail--; // 构造递增队列的
ans=max(ans,sum[i]-sum[q[head]]); // 取最大值
q[++tail]=i; // 扔进去
}
cout<<ans;
return 0;
}
end
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...