bzoj 4527

探讨了在给定数列中寻找最长子串,通过添加不超过k个数形成公差为d的等差数列的问题。文章详细介绍了算法思路,包括如何利用单调栈预处理最大最小值及线段树分治实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
给出一个数列a。
需要求出一个最长的子串加入不超过k个数,能够形成公差为d的等差数列。

题解:

形成公差为d的等差数列的条件:
1.不存在相同的数
2.所有的数应该在模d下同余
3.若设max为区间最大值,min为区间最小值,应该满足:
(maxmin)/d(ij)<=k

如何实现?

设b=a%d,c=a/d
先将b相同的一段段区间搞出来->for一遍

将上面的式子变一下:
max(c)min(c)+j<=k+i

考虑枚举右端点:
在同一个区间,维护左边的那个值的区间最小值。
对于一个右端点可以影响到的位置->可以用单调栈预处理最为最大最小值会影响到的位置。

维护左边的那个值的区间最小值,需要维护 max(c)+j min(c)+j 的区间最小值。
通过线段树分治可以找出对应位置。线段树分治,就是在线段树上找到对应区间然后再找对应的最左或者最右的位置。

对于,区间内出现相同的。。。不难的。

注意几点:
1.大视野此题数据弱,可以在codeforces上交407E
2.负数不能直接除

代码:
http://paste.ubuntu.com/24233592/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值