从左到右枚举优美区间的右端点,假设当前枚举到
i
i
i,那么区间
[
k
,
i
]
[k,i]
[k,i]为优美区间当且仅当
k
+
n
u
m
=
=
i
k+num==i
k+num==i
其中
n
u
m
num
num为
[
k
,
i
]
[k,i]
[k,i]中相差为
1
1
1的数对
(
a
,
b
)
(
a
<
b
)
(a,b)(a<b)
(a,b)(a<b)的数对个数
枚举到
i
i
i时我们将
a
[
i
]
+
1
a[i]+1
a[i]+1与
a
[
i
]
−
1
a[i]-1
a[i]−1的贡献计入
设
a
[
i
]
+
1
a[i]+1
a[i]+1所在位置为
p
1
p_1
p1,
a
[
i
]
−
1
a[i]-1
a[i]−1所在位置为
p
2
p_2
p2
那么若
p
i
(
i
=
1
,
2
)
<
i
p_i(i=1,2)<i
pi(i=1,2)<i且
p
i
>
0
p_i>0
pi>0时会对
[
1
,
p
i
]
[1,p_i]
[1,pi]产生
1
1
1的贡献
所以我们只需一棵兹磁区间加法与区间求最大值的线段树即可
我们用堆按从大到小维护
l
l
l,对于询问
(
l
,
r
)
(l,r)
(l,r),我们在线段树上查询
[
1
,
l
]
[1,l]
[1,l]的
k
+
n
u
m
k+num
k+num的最大值以及最大的
k
k
k,若
k
+
n
u
m
=
=
i
k+num==i
k+num==i则找到了该询问的答案,将该询问从堆中弹出,否则将其留在堆中,并枚举下一个
i
i
i
显然若存在优美区间
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1]与
[
l
2
,
r
2
]
[l_2,r_2]
[l2,r2]满足
l
2
<
r
1
l_2<r_1
l2<r1且互不包含,那么区间
[
l
2
,
r
1
]
[l_2,r_1]
[l2,r1]也是优美的,因此可以保证这样最优
Code
区间询问的第二种写法比第一种写法不知快到哪里去了
Pair ask(LL l,LL r,LL now,LL x,LL y){
if (x<=l && r<=y) return tr[now];
if (r<x || l>y) return Pair(0,0);
pd(now);
return max(ask(l,mid,lson,x,y),ask(mid+1,r,rson,x,y));
}
Pair ask(LL l,LL r,LL now,LL x,LL y){
if (x<=l && r<=y) return tr[now];
if (r<x || l>y) return Pair(0,0);
pd(now);
Pair res=Pair(0,0);
if (mid>=x) cmax(res,ask(l,mid,lson,x,y));
if (mid+1<=y) cmax(res,ask(mid+1,r,rson,x,y));
return res;
}