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

题目

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

思路

法一

首先 O ( n m ) O(nm) O(nm) 检验 l i ≤ k d ≤ r i l_i\le kd\le r_i likdri
意味着检验
⌈ l i k ⌉ ≤ d ≤ ⌊ r i k ⌋ \lceil\frac{l_i}{k}\rceil\le d\le \lfloor \frac{r_i}{k}\rfloor klidkri
此时发现右边可以数论分块,对于 k ∈ [ l , r ] k\in[l,r] k[l,r] 一段相同的右边值显然 k k k r r r 最优

	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;
		}
	}

但是这道题目有点卡,里面进行了 4 4 4 次除法
继续变形发现
⌊ l i − 1 k ⌋ < d ≤ ⌊ r i k ⌋ \lfloor \frac{l_i-1}{k}\rfloor< d\le \lfloor \frac{r_i}{k}\rfloor kli1<dkri
这时候可以一起分块了,但是注意 k = l i k=l_i k=li 时候是可以的
但是还是会 T 掉
然后发现可以
⌊ l i − 1 d ⌋ < ⌊ r i d ⌋ \lfloor \frac{l_i-1}{d}\rfloor< \lfloor \frac{r_i}{d}\rfloor dli1<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 ( n m ) O(n\sqrt m) O(nm )

法二

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

法三

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值