ABC 388 (DEG)

赛时4题,打得很差的一场。尤其是E题,赛时一直被卡,直到结束看群友的结论后顿然醒悟,不到3分钟码出并AC,只能恨自己赛时为什么这么sb...

D

模拟 + 差分

从左到右枚举i,每一次枚举可以计算出第i个人有多少颗糖(a[i] + 前面i1个人给的糖数num)。这样,第i个人会给出的糖数为:

numout = min(n - i, a[i] + num)

给后面的人糖的区间范围是[i+1,i+numout]。可以考虑设置差分数组stop,其中stop[i]表示枚举到第i个人时,前面i1个人刚刚开始停止给第i个人糖的人数。这样每次可以令stop[i+numout+1]++,用sumstop维护差分数组的前缀和,就是当前i1个人不给第i个人糖的人数。所以上述的num便可直接计算:

num = i - 1 - sum_stop

最后每个人的糖数即为:

max(0 , a[i] + num - (n - i))

具体细节见代码

code

E

贪心 + 思维,最想抽自己的一集

只需要注意答案数量不超过n/2。这样就能得到一个关键性质:前n/2个蛋糕一定放上面,后n/2个蛋糕一定放下面。(赛时因为没想到这个而坐牢1h...)

然后就没有然后了,直接前一半与后一半贪心匹配就好了,二分or双指针均可做。

code

G

二分 + ST表 + 推公式

这道题不能延续题解中E的做法,需要换一个思路。其实E还有另一种做法:
二分答案,然后取答案作为前后缀长度,这样转化为判断前后缀是否一 一匹配(证明不难,略)。

前后缀一 一匹配在E中可以线性双指针来判断,在G中就不行了,因为要对q个子数组判断,复杂度O(nq),故需要用一种更高效的方式来判断:

预处理a数组中每个位置i,满足:a[T[i]]>=2a[i]的第一个位置T[i]1<=i,T[i]<=n)。

对于询问区间[l,r],设二分的前后缀长度为k,则对于前缀中的某个位置il<=i<=l+k1),设在后缀中需要匹配的位置为pos,则有:

r - pos = l + k - 1 - i

pos=rlk+i+1。由于需要满足a[pos]>=2a[i]的性质,故:

T[i] <= pos = r - l - k + i + 1

将带i的式子移到不等式左侧,即为:

T[i] - i <= r - l - k + 1

这个不等式是对任意 l<=i<=l+k1 均要满足的,否则就会出现前后缀中某个位置失配的情况,而右侧为定值。故可写作:

max(T[i] - i) <= r - l - k + 1 (l <= i <= l + k - 1

因此,若上式满足,则当前二分的前后缀匹配,可以进一步扩大正在二分的答案k;若不满足,则前后缀失配,需要缩小正在二分的答案k

可以发现左边是求区间最大值,由于无修改,故可以用ST表预处理来维护区间T[i]i的最大值,且ST表的查询复杂度为O(1),相对于线段树可以少一个log复杂度。

总时间复杂度为O(qlogn+nlogn)

code

posted @   jxs123  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示
主题色彩