题目
思路
法一
首先
O
(
n
m
)
O(nm)
O(nm) 检验
l
i
≤
k
d
≤
r
i
l_i\le kd\le r_i
li≤kd≤ri
意味着检验
⌈
l
i
k
⌉
≤
d
≤
⌊
r
i
k
⌋
\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] 一段相同的右边值显然
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
⌊kli−1⌋<d≤⌊kri⌋
这时候可以一起分块了,但是注意
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
⌊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 ( 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,i−1] 但包含
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∈[ai−1+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
len≥d 的区间一定能统计入答案,
l
e
n
<
d
len<d
len<d 的最多只会被一个点覆盖
那么
l
e
n
≥
d
len\ge d
len≥d 的区间我们可以直接统计,
l
e
n
<
d
len<d
len<d 的插入树状数组后单点查询累加
时间复杂度
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)