首页 > 其他分享 >mex(权值线段树+线段树上二分)

mex(权值线段树+线段树上二分)

时间:2022-09-25 11:58:36浏览次数:70  
标签:val int 线段 mid mex seg 权值 id

 

 思路:首先看到区间维护,想到线段树,但是很明显无法用线段树直接维护区间最小没出现过的自然数,因为假若一个节点的左右儿子节点的值都为0,我们是无法推断出父节点的值是几的。

    然后这题看起来可以用扫描线做,但因为不是直接对最小没有出现过的自然数进行维护,所以似乎十分麻烦

    我们为了维护方便,直接建一棵权值线段树,即对答案区间的自然数建线段树(仔细观察,因为n个数最多只能占n个位置,答案区间是0到n);然后我们利用离线思想,从左向右扫,不断更新线段树(最后出现过的位置),在遇到询问的时候直接进行二分求满足条件的最小值就行

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
struct op {//线段树维护区间最小值
    int val;
}seg[4 * N];//每个值的出现位置
int n, q, a[N], _ans[N];
vector<pair<int,int>> lis[N];
void update(int id) {
    seg[id].val = min(seg[id * 2].val, seg[id * 2 + 1].val);
}
void change(int id, int l, int r, int pos, int val) {
    if (l == r) {
        seg[id].val = val;
        return;
    }
    else {
        int mid = (l + r) >> 1;
        if (mid >= pos) change(id * 2, l, mid, pos, val);
        else change(id * 2 + 1, mid + 1, r, pos, val);
        update(id);
    }
}
int query(int id, int l, int r, int val) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    if (seg[2 * id].val < val) return query(2 * id, l, mid, val);
    else return query(2 * id + 1, mid + 1, r, val);
}
int main() {
    scanf("%d%d", &n, &q); 
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]), a[i] = min(a[i], n + 1);
    for (int i = 1; i <= q; i++) {
        int l, r; 
        scanf("%d%d", &l, & r);
        lis[r].push_back({ l,i });
    }
    for (int i = 1; i <= n; i++) {
        change(1, 0, n + 1, a[i], i);
        for (auto t : lis[i]) {
            _ans[t.second] = query(1, 0, n + 1, t.first);
        }
    }
    for (int i = 1; i <= q; i++) printf("%d\n", _ans[i]);
    return 0;
}

 

      

标签:val,int,线段,mid,mex,seg,权值,id
From: https://www.cnblogs.com/Aacaod/p/16727561.html

相关文章

  • 树状数组和线段树资料
    例题和代码模板:https://www.cnblogs.com/pavtlly/p/9979702.html看老师这个博客链接吧 https://zhuanlan.zhihu.com/p/106118909线段树资料 线段树进阶资料(有兴......
  • 关于线段树的一点小笔记
    关于线段树的一点小笔记线段树:线段树是一棵天生支持单点修改、查询和区间查询的一棵完全二叉树,其单点修改、查询和区间修改的时间复杂度均为\(\Theta(\lgn)\)在区......
  • [CSharpTips]C# 判断一个点是否在线段上
    C#判断一个点是否在线段上usingSystem;usingSystem.Collections.Generic;usingSystem.Windows;namespacePointInLineTest{classProgram{s......
  • 【学习笔记/模板】吉司机线段树
    吉司机线段树这里不会挂涩图了,相册或者公告板自取调了一晚上,刚改出来,有时间再更。P6242【模板】线段树3Code#include<cstdio>#include<algorithm>#defineLLlon......
  • JAVA线段树模板
    publicclassLineTree{int[]tree,nums;intn;publicLineTree(int[]nums){this.nums=nums;n=nums.length;tree=newi......
  • T1033:计算线段长度(信息学一本通C++)
     目录[题目描述]已知线段的两个端点的坐标A(Xa,Ya),B(Xb,Yb),求线段AB的长度,保留到小数点后3位。[输入]第一行是两个实数Xa,Ya,即A的坐标。第二行是两个实数Xb,Yb,即B的......
  • 做题记录整理线段树2 P4513. 小白逛公园(2022/9/20)
    P4513.小白逛公园我们思考一个如何使用线段树维护这个答案,会发现l.r的答案=max(l,mid的答案,mid+1,r的答案,横跨两个区间的答案)那么我们现在再引入一个区间的最大前缀......
  • 洛谷P3372【模板】线段树1
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;intn,m,a[N];intadd[N*4];//账本longlongsum[N*4];//a[k]的区间和voidbuild(intk,intl,i......
  • And RMQ 势能线段树-用剪枝+单点修改实现区间修改
    https://codeforces.com/gym/103107/problem/AA.AndRMQtimelimitpertest3secondsmemorylimitpertest512megabytesinputstandardinputoutputstan......
  • 【刷题】【线段树】
    (1)Laz标记:题目:区区区间区区区间(nowcoder.com)题解摘自:区区区间_牛客博客(nowcoder.net)我们发现这个等差数列的等差为1。对于修改一段区间l-rl−r如果我们知道......