• bzoj3339


    线段树+离线

    这种题既可以用莫队做也可以用线段树做,跟hh的项链差不多

    首先我们处里出前缀mex,也就是1->i的mex值,再预处理出每个数下一次出现的位置,然后把每个前缀mex插入线段树,每个节点表示l==r表示1->l的mex,然后把询问按左端点排序,依次查询,修改每次把小于当前左端点的数的影响去除,也就是把i->nxt[i-1]的mex和a[i]取min,因为这些前缀mex的a[i]消失了,那么取min就是新答案,每次查询就是单点查询,也就是查询1->r的前缀mex,因为1-l-1的影响都被消除了,所以现在1-r的答案就是l-r的答案

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 200010, inf = 0x3f3f3f3f;
    struct query_ {
        int l, r, id;
        bool friend operator < (query_ A, query_ B)  {
            return A.l < B.l;
        }
    } q[N];
    int n, m;
    int nxt[N], tree[N << 2], tag[N << 2], a[N], ans[N], vis[N], last[N];
    void pushdown(int x)
    {
        if(tag[x] == inf) return;
        tag[x << 1] = min(tag[x << 1], tag[x]);
        tag[x << 1 | 1] = min(tag[x << 1 | 1], tag[x]);
        tree[x << 1] = min(tree[x << 1], tag[x]);
        tree[x << 1 | 1] = min(tree[x << 1 | 1], tag[x]);
        tag[x] = inf;
    } 
    void update(int l, int r, int x, int a, int b, int mn)
    {
        if(l > b || r < a) return;
        if(l >= a && r <= b)
        {
            tag[x] = min(tag[x], mn);
            tree[x] = min(tree[x], mn);
            return;
        }
        pushdown(x);
        int mid = (l + r) >> 1;
        update(l, mid, x << 1, a, b, mn);
        update(mid + 1, r, x << 1 | 1, a, b, mn);
        tree[x] = min(tree[x << 1], tree[x << 1 | 1]);
    }
    int query(int l, int r, int x, int pos)
    {
        if(l == r) 
        {
    //      printf("l = %d r = %d pos = %d tree[%d] = %d
    ", l, r, pos, x, tree[x]);
            return tree[x]; 
        }
        pushdown(x);
        int mid = (l + r) >> 1;
        if(pos <= mid) return query(l, mid, x << 1, pos);
        else return query(mid + 1, r, x << 1 | 1, pos);
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for(int i = 1; i <= m; ++i) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
        sort(q + 1, q + m + 1);
        int pos = 0;
        memset(tree, 0x3f3f, sizeof(tree));
        memset(tag, 0x3f3f, sizeof(tag));
        for(int i = 1; i <= n; ++i)
        {
            nxt[last[a[i]]] = i;
            last[a[i]] = i;
            vis[a[i]] = 1;
            while(vis[pos]) ++pos;
    //      printf("i = %d pos = %d
    ", i, pos);
            update(1, n, 1, i, i, pos);
        }
        for(int i = 1; i <= n; ++i) if(nxt[i] == 0) nxt[i] = n + 1;
        pos = 1;
        for(int i = 1; i <= m; ++i)
        {
            while(pos < q[i].l && pos <= n) 
            {
                update(1, n, 1, pos, nxt[pos] - 1, a[pos]);
        //      printf("pos = %d nxt[%d] = %d a[%d] = %d
    ", pos, pos, nxt[pos], pos, a[pos]);
                ++pos;
            }   
    //      printf("q[%d].l = %d q[%d].r = %d id = %d pos = %d
    ", i, q[i].l, i, q[i].r, q[i].id, pos);
            ans[q[i].id] = query(1, n, 1, q[i].r);      
        }
        for(int i = 1; i <= m; ++i) printf("%d
    ", ans[i]);
        return 0;
    } 
    View Code
  • 相关阅读:
    锁相环(PLL)的IP核调取及应用详解
    进阶项目(3)UART串口通信程序设计讲解
    基础项目(2)二选一数据选择器的设计
    读写储存器RAM IP核的调取及应用
    进阶项目(1)字符状态机讲解
    基础项目(1) 流水灯项目讲解
    只读储存器ROM IP核的调取及应用
    常见的关系运算符(移位运算符)
    常见的关系运算符(缩减运算符)
    乱七八糟
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7462676.html
Copyright © 2020-2023  润新知