题解:CF1684F Diverse Segments
思路
让我们把所有相同的数单拉出来,以
考虑枚举一个位置
那么显然,我们修改的区间必须包含
考虑维护
-
无论如何都有
R\ge b_{i-1} ,因此f_1,\dots,f_n 全局对b_{i-1} 取\max 。 -
当
L>b_j 时,必定有R\ge b_i 。因此f_{b_j+1},\dots,f_n 对b_i 取\max 。 -
当
L>b_{j+1} 时,已经不合法了,令f_{b_{j+1}+1},\dots,f_n 变为+\infty 。
所以只需要支持后缀取
对于每一种数都进行如上操作。最后枚举
时间复杂度为
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int n, m;
int a[maxn], a1[maxn];
vector<int> V[maxn];
int mx[maxn], minR[maxn];
int main(){
int T;
scanf("%d", &T);
while(T --){
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
a1[i] = a[i];
}
sort(a1 + 1, a1 + n + 1);
int k = unique(a1 + 1, a1 + n + 1) - a1 - 1;
for(int i = 1; i <= n; i ++){
a[i] = lower_bound(a1 + 1, a1 + k + 1, a[i]) - a1;
V[a[i]].push_back(i);
}
for(int i = 1; i <= m; i ++){
int l, r;
scanf("%d %d", &l, &r);
mx[l] = max(mx[l], r);
}
for(int i = 1; i <= n; i ++) mx[i] = max(mx[i - 1], mx[i]);
for(int i = 1; i <= k; i ++){
int l = 0;
for(int j = 0; j < V[i].size(); j ++){
while(l < j && mx[V[i][l]] < V[i][j]) l ++;
if(l == j || mx[V[i][l]] < V[i][j]) continue;
int x = V[i][l], y = V[i][j], z = V[i][l + 1], w = V[i][j - 1];
minR[0] = max(minR[0], w);
minR[x + 1] = max(minR[x + 1], y);
minR[z + 1] = n + 1;
}
}
int len = n + 1;
for(int i = 1; i <= n; i ++){
minR[i] = max(minR[i], max(minR[i - 1], i - 1));
if(minR[i] > n) break;
len = min(len, minR[i] - i + 1);
}
printf("%d\n", len);
for(int i = 0; i <= n; i ++) mx[i] = minR[i] = 0, V[i].clear();
}
return 0;
}