Description
Solution
算法一
考虑一个 O ( n q ) O(nq) O(nq) 的算法。
我们动态地维护序列 a a a,其中 a i a_i ai 表示 p i p_i pi 是 [ 1 , i ] [1,i] [1,i] 中第几小的。显然,有 a i = i − b i a_i=i-b_i ai=i−bi。
对于一次修改,直接
O
(
1
)
O(1)
O(1) 地更新
a
i
a_i
ai。
对于一次查询,令
a
n
s
=
a
i
ans=a_i
ans=ai,并从
i
+
1
i+1
i+1 一直扫描到
n
n
n。若当前的
a
n
s
ans
ans 满足
a
n
s
≥
a
j
ans \ge a_j
ans≥aj,那么就将
a
n
s
ans
ans 加上
1
1
1,否则不做操作。这里加
1
1
1 的实质是,由于
j
>
i
j>i
j>i 且
p
j
p_j
pj 在
[
1
,
j
]
[1,j]
[1,j] 中从小到大的排名比
[
1
,
j
−
1
]
[1,j-1]
[1,j−1] 中
p
i
p_i
pi 的排名要高,所以
p
j
<
p
i
p_j<p_i
pj<pi;此时,我们在
[
1
,
j
−
1
]
[1,j-1]
[1,j−1] 的排名列表中在
i
i
i 之前插入了一个位置,需将
a
n
s
ans
ans 加上
1
1
1 表示
i
i
i 在
[
1
,
j
]
[1,j]
[1,j] 中的排名。
ans=a[i];
for (int j=i+1;j<=n;j++)
if (ans>=a[j]) ans++;
最后输出 a n s ans ans 即可。
算法二
看到时限为 5.00s \text{5.00s} 5.00s 且 n , q ≤ 1 0 5 n,q \le 10^5 n,q≤105,根据 Codeforces \text{Codeforces} Codeforces 的做题经验,这显然是一道分块题(或者是一道树套树)。
考虑分块,令块长为 B B B。
对于每一个块,我们维护出一个列表 v v v。其实际意义是,若进入这个块时 a n s = x ans=x ans=x,那么最终从这个块出来时 a n s = v x + x ans=v_x+x ans=vx+x。
每次修改都是单点的,我们更新
a
i
a_i
ai 并重构该块的列表
v
v
v。
对于第一次查询,我们从左往右扫描,对于零散块直接在
a
a
a 中扫描并更新
a
n
s
ans
ans,对于整块直接调用列表更新
a
n
s
ans
ans。
显然,每次查询都是 O ( B + n B ) O(B+\frac n B) O(B+Bn) 的。关键在于,如何快速重构某一块的列表。
为方便叙述,令该块为 [ L , R ] [L,R] [L,R]。考虑从前往后扫描,实时维护一个数据结构,里面存储了若干个三元组 ( l , r , c ) (l,r,c) (l,r,c),表示将 v ∈ [ l , r ] v \in [l,r] v∈[l,r] 从块头推到当前位置时的值 v + c v+c v+c。每次更新的时候,我们通过二分找到 set \text{set} set 里面第一个满足 L ≤ a i L \le a_i L≤ai 的位置,并将该处的 ( l , r , c ) (l,r,c) (l,r,c) 段成 ( l , L − 1 , c ) (l,L-1,c) (l,L−1,c) 与 ( L , R , c + 1 ) (L,R,c+1) (L,R,c+1),将后者向后面一个 ( l , r , c ) (l,r,c) (l,r,c) 合并。接着,对于该位置往后的那一段后缀,将 c c c 全部加一。显然,这个数据结构需要维护单点查询,单点插入与区间加,采用平衡树即可。由于最多有 log n \log n logn 个区间,所以单次重构是 O ( B log B ) O(B \log B) O(BlogB) 的。
总复杂度 O ( q ( B + n B + B log B ) ) O(q(B+\frac n B+ B \log B)) O(q(B+Bn+BlogB))。当 n = 1 0 5 , q = 1 0 5 n=10^5,q=10^5 n=105,q=105 时,取 B = 120 B=120 B=120 理论最优,实际应将 B B B 调小(平衡树的常数很大)。
值得一提的是,若不维护若干个三元组,而用线段树维护长度为 n n n 的序列,那么复杂度就是 O ( q ( B + n B + B log n ) ) O(q(B+\frac n B+B \log n)) O(q(B+Bn+Blogn)),理论劣于上面的解法。但是,线段树常数较小,所以其实二者差不太多。