[线段树] [Hash] [BZOJ2124] 等差子数列

题目传送门
好久之前做过WC2015教师测试(大概是今年年初),CCF也是醉了搬了三道题考老师……
第一题是没有上司的舞会,题面被改成了猴腮雷……啊一遍树形DP就行了很休闲的就写了题解……
这是第二题,(就是从BZ的非权限题里扒了一道吗……)
暴力三元组是 n 3 n^3 n3的过不去……
考虑对每个位置加入对应数据的过程,记一个序列 a n a_n an,初始均为 0 0 0。如果我们加入 i i i,就把 a i a_i ai变成 1 1 1(略相当于变成 n n n进制数操作……)。
那么如果 a i a_i ai要成为等差三元组的中间项,就需要 a j = 1 a_j=1 aj=1并且 a 2 i − j = 0 a_{2i-j}=0 a2ij=0,其中 i > j i>j i>j
这个很显然吧…… 2 i − j > i 2i-j>i 2ij>i,既然它没在 [ 1 , i ] [1,i] [1,i]里出现,那么根据排列的性质它一定会在 [ i + 1 , n ] [i+1,n] [i+1,n]中出现,这样就能构成等差三元组了。
那么每次修改时,枚举中间数判断是 n 2 n^2 n2的,还是过不去……
这里就用到了Hash,对于这个 01 01 01序列做正反两遍Hash,用线段树维护Hash值,那么影响的范围就是 [ 1 , h ] [1,h] [1,h] [ h , n ] [h,n] [h,n](记要更改的数为 h h h),每次查询这两个区间和对称区间就行了,判断左端的正Hash值与右端的反Hash值是否相等,不相等就有解。
时间复杂度 O ( T n log ⁡ 2 n ) O(Tn\log_2 n) O(Tnlog2n)
Code
貌似改后就是加强了一下数据……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值