羊夏菡 发表于 2026-2-2 23:15:02

洛谷 P3503 [POI 2010] KLO-Blocks 题解

Solution

双指针做法。
本文中合法子段指一段高度 \(\ge k\) 的连续堆。
观察数据范围,发现 \(O(nm)\) 可过。于是考虑对于每个 \(k\) 都 \(O(n)\) 做一遍。
看到最长子段问题,尝试双指针。设以 \(l\) 为左端点的最长合法子段右端点为 \(r\)。易证 \(l\) 递增时 \(r\) 单调不降。
于是只需要 \(O(1)\) 判断一个区间 \(\) 是否合法。显然贪心地把左右两边所有木块尽量往这个区间上集中。设 \(pre_i\) 为第 \(1\sim i\) 堆最多能向 \(i+1\) 贡献多少个木块,\(suf_i\) 同理。\(pre,suf\) 均可以 \(O(n)\) 递推处理。
此时 \(\) 合法等价于 \(pre_{l-1}+suf_{r+1}+\sum_{i=l}^r a_i\le k\cdot (r-l+1)\)。可以 \(O(1)\) 判断。
时间复杂度 \(O(nm)\)。
Code

#include #define rept(i,a,b) for(int i(a);i=b;--i)#define int long longusing namespace std;const int N=1e6+5;int a,s,pre,suf,n,m,k,ans;bool check(int l,int r){    return pre+suf+s-s>=k*(r-l+1);}signed main(){    cin.tie(0)->sync_with_stdio(0);    cin>>n>>m;    rept(i,1,n) cin>>a,s=s+a;    while(m--){      ans=0;      cin>>k;      rept(i,1,n) pre=max(0ll,a+pre-k);      pert(i,n,1) suf=max(0ll,a+suf-k);      for(int l=1,r=0;l

泠邸 发表于 2026-2-3 04:25:25

分享、互助 让互联网精神温暖你我

崔瑜然 发表于 2026-2-5 03:04:08

懂技术并乐意极积无私分享的人越来越少。珍惜

眩疝诺 发表于 2026-2-5 11:16:22

收藏一下   不知道什么时候能用到

贺蛟亡 发表于 2026-2-7 05:49:21

谢谢分享,辛苦了

羊夏菡 发表于 2026-2-8 02:05:55

谢谢分享,试用一下

闹忧踫 发表于 2026-2-8 04:22:43

懂技术并乐意极积无私分享的人越来越少。珍惜

毡轩 发表于 2026-2-8 11:44:06

感谢分享,下载保存了,貌似很强大

季卓然 发表于 2026-2-9 06:13:47

感谢发布原创作品,程序园因你更精彩

即息极 发表于 2026-2-9 17:27:54

感谢发布原创作品,程序园因你更精彩

泠邸 发表于 2026-2-10 03:44:52

收藏一下   不知道什么时候能用到

颜清华 发表于 2026-2-11 12:16:51

谢谢分享,辛苦了

庇床铍 发表于 2026-2-24 04:53:35

前排留名,哈哈哈

班嘉淑 发表于 2026-3-3 12:09:48

感谢,下载保存了

即息极 发表于 2026-3-3 13:39:32

这个好,看起来很实用

兼罔 发表于 2026-3-6 10:21:29

东西不错很实用谢谢分享

邰怀卉 发表于 1 小时前

感谢分享,下载保存了,貌似很强大
页: [1]
查看完整版本: 洛谷 P3503 [POI 2010] KLO-Blocks 题解