当前位置: 代码迷 >> 综合 >> Snuke Line[ARC068C][分块][主席树][BIT]
  详细解决方案

Snuke Line[ARC068C][分块][主席树][BIT]

热度:13   发布时间:2023-11-19 09:55:42.0

文章目录

  • 题目
  • 思路
    • 法一
    • 法二
    • 法三

题目

在这里插入图片描述
Luogu
在这里插入图片描述

思路

法一

首先 O(nm)O(nm)O(nm) 检验 li≤kd≤ril_i\le kd\le r_ili?kdri?
意味着检验
?lik?≤d≤?rik?\lceil\frac{l_i}{k}\rceil\le d\le \lfloor \frac{r_i}{k}\rfloor?kli???d?kri???
此时发现右边可以数论分块,对于 k∈[l,r]k\in[l,r]k[l,r] 一段相同的右边值显然 kkkrrr 最优

	for(int i=1;i<=n;i++){
    int p=read(),q=read(),L,R=m+1;for(int l=1,r;l<=q;l=r+1){
    r=q/(q/l);L=(p+r-1)/r,R=min(R,q/l);if(L<=R)cha[L]++,cha[R+1]--,R=L-1;}}

但是这道题目有点卡,里面进行了 444 次除法
继续变形发现
?li?1k?<d≤?rik?\lfloor \frac{l_i-1}{k}\rfloor< d\le \lfloor \frac{r_i}{k}\rfloor?kli??1??<d?kri???
这时候可以一起分块了,但是注意 k=lik=l_ik=li? 时候是可以的
但是还是会 T 掉
然后发现可以
?li?1d?<?rid?\lfloor \frac{l_i-1}{d}\rfloor< \lfloor \frac{r_i}{d}\rfloor?dli??1??<?dri???
就可以过了

for(int i=1;i<=n;i++){
    int p=read()-1,q=read();cha[p+1]++,cha[q+1]--;for(int l=1,r;l<=p;l=r+1){
    r=min(p/(p/l),q/(q/l));if(p/l<q/l)cha[l]++,cha[r+1]--;}
}

时间复杂度 O(nm)O(n\sqrt m)O(nm ?)

法二

假设现在计算 ddd 的种类,对于到达时刻集合 {a1,a2,...a,t}\{a_1,a_2,...a,_t\}{ a1?,a2?,...a,t?}
我们可以统计出 fif_ifi? 不包含 aj,j∈[1,i?1]a_j,j\in[1,i-1]aj?,j[1,i?1] 但包含 aia_iai? 的个数
然后累加即可
发现等于每次查询 l∈[ai?1+1,ai],r∈[ai,m]l\in[a_{i-1}+1,a_i],r\in[a_i,m]l[ai?1?+1,ai?],r[ai?,m] 的区间个数,可以用主席树实现
时间复杂度 O(nlog2n)O(nlog^2n)O(nlog2n)

法三

很巧妙,我们从小到大枚举 ddd ,发现 len≥dlen\ge dlend 的区间一定能统计入答案, len<dlen<dlen<d 的最多只会被一个点覆盖
那么 len≥dlen\ge dlend 的区间我们可以直接统计,len<dlen<dlen<d 的插入树状数组后单点查询累加
时间复杂度 O(nlog2n)O(nlog^2n)O(nlog2n)

  相关解决方案