BZOJ3585/洛谷P4137 区间mex(主席树)
程序员文章站
2024-03-03 16:45:40
...
题意
有 个数 ,有 个询问,每个询问给定 ,求 的 。(最小的未出现的自然数)
其中
分析
令 表示 最后出现的位置。用主席树维护 。
那么对于一个询问 ,我们在 中的权值线段树上二分第一个比 小的数的位置即可,二分可以通过维护最小值来解决。
时空复杂度 。
代码如下
#include <bits/stdc++.h>
#define lson l, m, lch[rt]
#define rson m + 1, r, rch[rt]
using namespace std;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
const int N = 200005;
int cnt, lch[N * 33], rch[N * 33], val[N * 33], root[N], las[N];
void update(int l, int r, int &rt, int las, int p, int c){
rt = ++cnt;
lch[rt] = lch[las], rch[rt] = rch[las];
if(l == r){
val[rt] = c;
return;
}
int m = l + r >> 1;
if(p <= m) update(lson, lch[las], p, c);
else update(rson, rch[las], p, c);
val[rt] = min(val[lch[rt]], val[rch[rt]]);
}
int query(int l, int r, int rt, int k){
if(l == r) return l;
int m = l + r >> 1;
if(val[lch[rt]] >= k) return query(rson, k);
return query(lson, k);
}
int main(){
int i, j, n, m, a, b;
n = read(); m = read();
for(i = 1; i <= n; i++) j = read(), update(0, 1e9, root[i], root[i - 1], j, i);
for(i = 1; i <= m; i++){
a = read(); b = read();
printf("%d\n", query(0, 1e9, root[b], a));
}
return 0;
}
上一篇: java泛型详解