选取一个
t
t
t ,并选取环上一物品
x
x
x ,在
t
t
t 时刻从
x
x
x 出发,每单位时间前进一步,要求如果经过的第
i
i
i 个物品(出发处为第
0
0
0 个物品)出现时间为
k
k
k ,则需要满足
t
+
i
≥
k
t+i\ge k
t+i≥k (在出现时或之后才能标记到这个物品),求最小的
t
t
t ,答案即为
t
min
+
n
−
1
t_{\min}+n-1
tmin+n−1
考虑将
T
T
T 数组复制一遍
然后限制条件变成
∀
x
≤
i
≤
x
+
n
−
1
,
t
+
i
−
x
≥
T
i
\forall x\le i\le x+n-1,t+i-x\ge T_i
∀x≤i≤x+n−1,t+i−x≥Ti
于是当
x
x
x 固定时
t
=
max
i
=
x
x
+
n
−
1
{
T
i
−
i
}
+
x
t=\max_{i=x}^{x+n-1}\{T_i-i\}+x
t=i=xmaxx+n−1{Ti−i}+x
而由于
T
T
T 数组倍长过,所以
T
i
+
n
=
T
i
T_{i+n}=T_i
Ti+n=Ti
故对于所有的
i
∈
[
1
,
n
]
i\in[1,n]
i∈[1,n] 都有
T
i
−
i
>
T
i
+
n
−
(
i
+
n
)
T_i-i>T_{i+n}-(i+n)
Ti−i>Ti+n−(i+n)
所以可以把
max
\max
max 的上界改成
2
n
2n
2n
t
=
max
i
=
x
2
n
{
T
i
−
i
}
+
x
t=\max_{i=x}^{2n}\{T_i-i\}+x
t=i=xmax2n{Ti−i}+x
设
a
i
=
T
i
−
i
a_i=T_i-i
ai=Ti−i ,
b
b
b 为
a
a
a 的后缀最大值数组,那么
t
min
t_{\min}
tmin 就是
min
x
=
1
n
{
b
x
+
x
}
\min_{x=1}^n\{b_x+x\}
x=1minn{bx+x}
显然,如果
b
b
b 在区间
[
l
,
r
]
[l,r]
[l,r] 上相等,那么
x
x
x 取
l
l
l 比取
l
+
1
l+1
l+1 到
r
r
r 的任意一个数都优
所以
t
min
t_{\min}
tmin 再次化为
min
x
=
1
n
{
b
x
+
x
}
[
x
=
1
OR
b
x
−
1
>
b
x
]
\min_{x=1}^n\{b_x+x\}[x=1\text{ OR }b_{x-1}>b_x]
x=1minn{bx+x}[x=1 OR bx−1>bx]
设有数组
c
c
c ,保存在
[
1
,
n
]
[1,n]
[1,n] 内满足
b
i
>
b
i
+
1
b_i>b_{i+1}
bi>bi+1 (换句话说,
i
i
i 是
a
a
a 数组的以
i
i
i 为开头的前缀最大值)的所有位置
i
i
i ,设这样的二元组共
m
m
m 个
则显然
i
i
i 从
1
1
1 到
m
m
m ,
a
c
i
a_{c_i}
aci 严格单调递减,
t
min
t_{\min}
tmin 再次转化
min
(
min
i
=
1
m
−
1
{
a
c
i
+
1
+
c
i
+
1
}
,
a
c
1
+
1
,
c
m
+
1
+
max
i
=
n
+
1
2
n
{
T
i
−
i
}
)
\min(\min_{i=1}^{m-1}\{a_{c_{i+1}}+c_i+1\},a_{c_1}+1,c_m+1+\max_{i=n+1}^{2n}\{T_i-i\})
min(i=1minm−1{aci+1+ci+1},ac1+1,cm+1+i=n+1max2n{Ti−i})
于是我们需要维护
c
c
c 数组的
c
1
,
c
m
c_1,c_m
c1,cm 以及
min
i
=
1
m
−
1
{
a
c
i
+
1
+
c
i
+
1
}
\min_{i=1}^{m-1}\{a_{c_{i+1}}+c_i+1\}
mini=1m−1{aci+1+ci+1}
在这里需要让
q
u
e
r
y
(
u
,
x
)
query(u,x)
query(u,x) 返回一个三元组
(
l
,
r
,
v
a
l
)
(l,r,val)
(l,r,val)
分别表示
c
c
c 的第一个元素、最后一个元素、对应的
min
i
=
1
m
−
1
{
a
c
i
+
1
+
c
i
+
1
}
\min_{i=1}^{m-1}\{a_{c_{i+1}}+c_i+1\}
mini=1m−1{aci+1+ci+1}
同时我们发现我们没必要维护倍长后的后半段
因为我们只需要查询
q
u
e
r
y
(
r
o
o
t
,
max
i
=
n
+
1
2
n
{
T
i
−
i
}
)
query(root,\max_{i=n+1}^{2n}\{T_i-i\})
query(root,maxi=n+12n{Ti−i}) 即可
r
o
o
t
root
root 为线段树的根
而
max
i
=
n
+
1
2
n
{
T
i
−
i
}
=
−
n
+
max
i
=
1
n
{
T
i
−
i
}
\max_{i=n+1}^{2n}\{T_i-i\}=-n+\max_{i=1}^n\{T_i-i\}
maxi=n+12n{Ti−i}=−n+maxi=1n{Ti−i}
复杂度
O
(
n
log
2
n
)
O(n\log^2n)
O(nlog2n)
Code
#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define For(i, a, b) for (i = a; i <= b; i++)#define p2 p << 1#define p3 p << 1 | 1inlineintread(){int res =0;bool bo =0;char c;while(((c =getchar())<'0'|| c >'9')&& c !='-');if(c =='-') bo =1;else res = c -48;while((c =getchar())>='0'&& c <='9')
res =(res <<3)+(res <<1)+(c -48);return bo ?~res +1: res;}template<classT>inline T Max(const T &a,const T &b){return a > b ? a : b;}template<classT>inline T Min(const T &a,const T &b){return a < b ? a : b;}constint N =1e5+5, M = N <<2, INF =0x3f3f3f3f;int n, m, p, t[N], lst, maxt[M];struct node
{int firs, lsts, firv, res;} ri[M];
node query(int l,int r,int downs,int p){if(l == r)return maxt[p]>= downs ?(node){l, r, maxt[p], INF}:(node){0,0,0, INF};int mid = l + r >>1;if(maxt[p3]< downs)returnquery(l, mid, downs, p2);if(maxt[p2]< maxt[p3])returnquery(mid +1, r, downs, p3);
node ls = ri[p], rs =query(mid +1, r, downs, p3);if(!ls.firs)return rs;return(node){ls.firs, rs.lsts, ls.firv,Min(Min(ls.res, rs.res),
rs.firv + ls.lsts +1)};}voidbuild(int l,int r,int p){if(l == r)return(void)(maxt[p]= t[l]- l);int mid = l + r >>1;build(l, mid, p2);build(mid +1, r, p3);
maxt[p]=Max(maxt[p2], maxt[p3]);
ri[p]=query(l, mid, maxt[p3], p2);}voidchange(int l,int r,int pos,int v,int p){if(l == r)return(void)(maxt[p]= v);int mid = l + r >>1;if(pos <= mid)change(l, mid, pos, v, p2);elsechange(mid +1, r, pos, v, p3);
maxt[p]=Max(maxt[p2], maxt[p3]);
ri[p]=query(l, mid, maxt[p3], p2);}intmain(){int i, x, y;
n =read(); m =read(); p =read();
For (i,1, n) t[i]=read();build(1, n,1);
node res =query(1, n, maxt[1]- n,1);
lst =Min(res.res, t[res.firs]- res.firs +1);if(res.lsts < n) lst =Min(lst, maxt[1]- n + res.lsts +1);printf("%d\n", lst += n -1);while(m--){
x =read(); y =read();if(p) x ^= lst, y ^= lst;change(1, n, x, y - x,1); t[x]= y;
res =query(1, n, maxt[1]- n,1);
lst =Min(res.res, t[res.firs]- res.firs +1);if(res.lsts < n) lst =Min(lst, maxt[1]- n + res.lsts +1);printf("%d\n", lst += n -1);}return0;}