概述
目录
- 问题
- 分析
- 代码
问题
- 长度为n的自然数序列,求任意区间内未出现过的最小自然数。长度n、询问次数m、自然数
a
i
a_i
ai满足:
- 1 ≤ n , m ≤ 200000 1leq n,mleq 200000 1≤n,m≤200000
- 0 ≤ a i ≤ 1000000000 0 leq a_i leq 1000 000 000 0≤ai≤1000000000
分析
- 序 → rightarrow → 时间
- 各时刻的线段树维护区间内的各数最后一次出现的位置的最小值
- 增量持久化策略优化线段树
- 大于n的 a i a_i ai 按n+1处理
代码
#include<bits/stdc++.h>
using namespace std;
const int MXN = 2e5+5;
int N, M, tot, ver[MXN];
struct TreeNode{
int l, r; // 左右子树
int p; // 各数的最后位置的最小值
}tree[MXN<<5];
void pushup(int root){
TreeNode &rt = tree[root];
TreeNode &ls = tree[rt.l], &rs = tree[rt.r];
rt.p = min(ls.p, rs.p);
}
int build(int l, int r){
int root = ++tot;
TreeNode &rt = tree[root];
rt.p = 0, rt.l = 0, rt.r = 0;
return root;
}
int change(int node, int l, int r, int x, int p){ // x在p位置上出现
int root = ++tot;
TreeNode &rt = tree[root];
rt = tree[node];
if(l == r) {rt.p = p; return root;}
int mid = (l+r)>>1;
if(x <= mid) rt.l = change(rt.l, l, mid, x, p);
else rt.r = change(rt.r, mid+1, r, x, p);
pushup(root);
return root;
}
int query(int node, int L, int R, int l, int r){
if(l == r) return l;
TreeNode &rt = tree[node];
TreeNode &ls = tree[rt.l], &rs = tree[rt.r];
int mid = (l+r)>>1;
if(ls.p < L) return query(rt.l, L, R, l, mid);
else if(rs.p < L) return query(rt.r, L, R, mid+1, r);
else return R;
}
int main(){
int t, x, L, R;
scanf("%d", &t);
while(t--){
tot = 0;
scanf("%d%d", &N, &M);
ver[0] = build(0, N+1);
for(int i = 1; i <= N; ++i){
scanf("%d", &x);
if(x > N) x = N+1;
ver[i] = change(ver[i-1], 0, N+1, x, i);
}
while(M--){
scanf("%d%d", &L, &R);
printf("%dn", query(ver[R], L, R, 0, N+1));
}
}
return 0;
}
最后
以上就是炙热心情为你收集整理的Mex函数(可持久化线段树)问题分析代码的全部内容,希望文章能够帮你解决Mex函数(可持久化线段树)问题分析代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复