0%

Codeforces Round 1083 (Div. 2)——CF-2205-D. Simons and Beating Peaks(笛卡尔树)

题目大意

题目描述

定义一个长度为 mm 的数组 bb 是“好的”,当且仅当不存在任何索引 ii1<i<m1 < i < m)满足 bi=max({bi1,bi,bi+1})b_i = \max(\{b_{i-1}, b_i, b_{i+1}\})

给定一个长度为 nn 的排列 aa。如果数组不是“好的”,你可以反复执行以下操作:
选择一个满足 ai=max({ai1,ai,ai+1})a_i = \max(\{a_{i-1}, a_i, a_{i+1}\}) 的索引 ii1<i<n1 < i < n)。然后,你可以从数组中删除 ai1a_{i-1} ai+1a_{i+1}。删除后,数组的左右两部分会重新拼接在一起。

求出使初始排列 aa 变为“好的”所需的最小操作次数。

输入格式

第一行包含一个整数 tt1t51041 \le t \le 5 \cdot 10^4),表示测试用例的数量。

对于每个测试用例:
第一行包含一个整数 nn3n51053 \le n \le 5 \cdot 10^5),表示排列的长度。
第二行包含 nn 个互不相同的整数 a1,a2,,ana_1, a_2, \ldots, a_n1ain1 \le a_i \le n),表示初始的排列。

保证所有测试用例中 nn 的总和不超过 51055 \cdot 10^5

输出格式

对于每个测试用例,输出一个整数,表示使数组变为“好的”所需的最小操作次数。

样例

输入

1
2
3
4
5
6
7
8
9
10
11
5
3
1 2 3
5
4 1 3 2 5
6
4 5 3 6 2 1
7
6 5 1 7 4 2 3
15
7 4 10 12 9 14 5 3 8 11 1 15 2 13 6

输出

1
2
3
4
5
0
1
3
3
9

样例解释

在第一组测试用例中,数组初始时已经是“好的”,因此不能执行任何操作,答案为 00

在第二组测试用例中,可以进行如下操作:
选择索引 33,此时满足 a3=max({a2,a3,a4})a_3 = \max(\{a_2, a_3, a_4\})(即 3=max({1,3,2})3 = \max(\{1, 3, 2\}))。接着从数组中移除 a2a_2(元素 11)。数组变为 [4,3,2,5][4, 3, 2, 5]
此时数组已经是“好的”,因此答案为 11

在第三组测试用例中,可以进行如下操作:
选择索引 22。从数组中移除 a1a_1。数组变为 [5,3,6,2,1][5, 3, 6, 2, 1]
选择索引 33。从数组中移除 a2a_2。数组变为 [5,6,2,1][5, 6, 2, 1]
选择索引 22。从数组中移除 a1a_1。数组变为 [6,2,1][6, 2, 1]
通过上述 33 次操作,数组变为“好的”。

image

思路讲解

官方解法是这个笛卡尔树,不过我不太会这个东西,我们来看看其他做法吧。

https://www.luogu.com.cn/article/h4sddubz

这个 luogu 题解抓住了最大值一定不会被删除这个特性。(并不是删除最大值不优秀,而是重新阅读题面,你会发现)

我们最终采用的呢,是递归式求解做法啊,也就是分治做法,配合使用的那个ST表。

这个是利用了最大值一定不会被删除的这个特性,而且还利用了一个特性,就是只要这个最大值它不在L或者不在R,一定要把L旁边的或者R旁边的全部给删掉

1
2
3
4
5
6
7
8
9
10
auto solve=[&](auto && self,ll l,ll r) -> ll {
if (l>=r) {
return 0;
}
ll mx_i=st.query(l,r);
ll tmp1=self(self,l,mx_i-1);
ll tmp2=self(self,mx_i+1,r);
ll res=min(tmp1 + r-mx_i ,tmp2 + mx_i-l);
return res;
};

AC代码

AC
https://codeforces.com/contest/2205/submission/365029208

心路历程(WA,TLE,MLE……)

C++ 14下,因为必须传入模板参数,嗯,可以这样子写其模板类型。

1
ST<ll,decltype(max_i)> st(N,vec_idx,max_i);

嗯,我们可以看到,嗯,这里应该是减L,不应该是减1。

1
2
3
4
5
6
7
8
9
10
auto solve=[&](auto && self,ll l,ll r) -> ll {
if (l>=r) {
return 0;
}
ll mx_i=st.query(l,r);
ll tmp1=self(self,l,mx_i-1);
ll tmp2=self(self,mx_i+1,r);
ll res=min(tmp1 + r-mx_i ,tmp2 + mx_i-l);
return res;
};