1 条题解

  • 0
    @ 2025-8-24 21:56:53

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar RabbitHu
    这个家伙很懒,早就退役啦

    搬运于2025-08-24 21:56:53,当前版本为作者最后更新于2018-02-25 16:59:30,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    您们这个莫队……每次移动左右端点时找新的答案那部分……一会O(1)O(1)一会O(n)O(n)……复杂度我不会证啊……

    于是……

    一个不用莫队的题解!

    从左往右扫一遍,在权值线段树(要可持久化一下)上修改当前权值对应的“最后一次出现的位置”为当前位置。

    查询区间[l,r][l, r]时,答案就是第rr棵线段树上,第一个“最后一次出现的位置”小于ll的权值。

    其实不可持久化也是可以的——只要把询问离线一下就好了。

    (可是我觉得在线算法更可爱 =v=)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #define space putchar(' ')
    #define enter putchar('\n')
    typedef long long ll;
    using namespace std;
    template <class T>
    void read(T &x){
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
    	if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
    	x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x){
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    
    const int N = 400005, M = 5000005;
    int n, m, a[N], lst[N], idx;
    int tot, root[N], ls[M], rs[M], data[M];
    
    void change(int old, int &k, int l, int r, int p, int x){
        k = ++tot;
        ls[k] = ls[old], rs[k] = rs[old];
        if(l == r) return (void)(data[k] = x);
        int mid = (l + r) >> 1;
        if(p <= mid) change(ls[old], ls[k], l, mid, p, x);
        else change(rs[old], rs[k], mid + 1, r, p, x);
        data[k] = min(data[ls[k]], data[rs[k]]);
    }
    int query(int k, int l, int r, int x){
        if(!k || l == r) return lst[l];
        int mid = (l + r) >> 1;
        if(data[ls[k]] >= x) return query(rs[k], mid + 1, r, x);
        return query(ls[k], l, mid, x);
    }
    
    int main(){
    
        read(n), read(m);
        lst[++idx] = 0;
        for(int i = 1; i <= n; i++)
    	read(a[i]), lst[++idx] = a[i], lst[++idx] = a[i] + 1;
        sort(lst + 1, lst + idx + 1);
        idx = unique(lst + 1, lst + idx + 1) - lst - 1;
        for(int i = 1; i <= n; i++){
            a[i] = lower_bound(lst + 1, lst + idx + 1, a[i]) - lst;
            change(root[i - 1], root[i], 1, idx, a[i], i);
        }
        while(m--){
            int l, r;
            read(l), read(r);
            write(query(root[r], 1, idx, l)), enter;
        }
    
        return 0;
    }
    
    • 1

    信息

    ID
    3096
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者