0%

START202——Min-Max Deque

思路讲解

首先,做这道题目,需要有简单版的基础,简单版就是一个简单的贪心。以下是简单版的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FOR(i,2,N){
if(i&1){
if(q.back()>=q.front()){
q.EF(A[i]);
}else{
q.EB(A[i]);
tr.update(i,i);
}
}else{
if(q.back()<=q.front()){
q.EF(A[i]);
}else{
q.EB(A[i]);
tr.update(i,i);
}
}
}
ll ans=min(q.back(),q.front());

那复杂版就是多了一个在线修改+询问,一个询问就是把 A[p]:=xA[p]:=x,然后 naive 的想法就是再跑一遍简单版的程序,当然,不难发现,时间复杂度肯定有问题。

经过简单尝试,我们发现这个贪心算法不是很好优化,因此我们可以想办法改进一下我们的这个贪心做法。

我们发现比较难优化,是因为我们想通过一种方法直接O(logn)O(\log n) 的时间复杂度内得到答案,这无疑有一定的难度。

那么,我们能不能在 O(logn)O(\log n) 的时间复杂度内判断一个答案可不可行那?

这肯定是比之前的问题简单多了,但也没有那么简单。

假设答案为 XX,将原数组 AA 表示为 0101...0101...00 代表 <X<X11 代表 X≥X
我们不难发现(在题设保证 N 为奇数的情况下):

  1. 越后出现越重要。

  2. 1010110101 为相持阶段,得到的 BB1111 类型,或维持原类型(即不能抵消 00)。

  3. 出现 1111 即使得 BB 变为 1111 类型(抵消一个 00)。

  4. 同理,出现 0000 即使得 BB 变为 0000 类型(抵消一个 11)。

那么通过上面发现的性质,那么我们其实就是要找到 1111 & 0000 的最靠右出现位置,这个可以使用二分答案+线段树二分 or 二分答案+二分+线段树解决。

具体来说是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  auto check=[&](int mid){
int pos00=tr.closer00(N,mid);
int pos11=tr.closer11(N,mid); // 使用线段树上二分实现
// pos00==-1 && pos11==-1 说明为1010结构,合法
return pos11>=pos00;
};
auto cal=[&](){
int l=1,r=N;
while (l<r) {
int mid=l+r+1>>1;
if(check(mid)){
l=mid;
}else{
r=mid-1;
}
}
return l;
};

代码:
https://www.codechef.com/viewsolution/1188151973

时间复杂度O(nlog2n)O(n\log^2n)

AC代码

https://www.codechef.com/viewsolution/1188151973

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