zoukankan      html  css  js  c++  java
  • BZOJ 3585: mex( 离线 + 线段树 )

    离线, 询问排序.

    先处理出1~i的答案, 这样可以回答左端点为1的询问.完成后就用seq(1)将1到它下一次出现的位置前更新. 不断这样转移就OK了

    --------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define M(l, r) (((l) + (r)) >> 1)
     
    const int maxn = 200009;
     
    int id[maxn], N = 0, seq[maxn], n, T[maxn];
    bool F[maxn];
     
    struct link {
    int pos;
    link* next;
    } A[maxn], *head[maxn], *pit = A;
     
    struct Q {
    int l, r, p;
    inline void read(int _p) {
    scanf("%d%d", &l, &r); l--; r--;
    p = _p;
    }
    bool operator < (const Q &q) const {
    return l < q.l;
    }
    } B[maxn];
     
    struct Node {
    Node *l, *r;
    int tag;
    Node() {
    tag = -1;
    l = r = NULL;
    }
    inline void pushdown() {
    if(~tag) {
    l->tag = ~l->tag ? min(l->tag, tag) : tag;
    r->tag = ~r->tag ? min(r->tag, tag) : tag;
    tag = -1;
    }
    }
    } pool[maxn << 1], *pt = pool, *root;
     
    void build(Node* t, int l, int r) {
    if(r > l) {
    int m = M(l, r);
    build(t->l = pt++, l, m);
    build(t->r = pt++, m + 1, r);
    } else
       t->tag = T[l - 1];
    }
     
    int L, R, v;
     
    void modify(Node* t, int l, int r) {
    if(L <= l && r <= R)
       t->tag = ~t->tag ? min(t->tag, v) : v;
    else {
    t->pushdown();
    int m = M(l, r);
    if(L <= m) modify(t->l, l, m);
    if(m < R) modify(t->r, m + 1, r);
    }
    }
    int query(Node* t, int l, int r) {
    if(l == r)
       return t->tag;
    t->pushdown();
    int m = M(l, r);
    return L <= m ? query(t->l, l, m) : query(t->r, m + 1, r);
    }
     
    int ans[maxn];
     
    int main() {
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
    memset(head, 0, sizeof head);
    memset(F, false, sizeof F);
    int m;
    cin >> n >> m;
    for(int i = 0; i < n; i++) {
    scanf("%d", seq + i);
    id[i] = seq[i];
    }
    sort(id, id + n);
    N = unique(id, id + n) - id;
    for(int i = 0; i < n; i++)
       seq[i] = lower_bound(id, id + N, seq[i]) - id;
    for(int i = n - 1; ~i; i--) {
    int t = seq[i];
    pit->pos = i;
    pit->next = head[t];
    head[t] = pit++;
    }
    for(int i = 0; i < n; i++) {
    if(id[seq[i]] < maxn) F[id[seq[i]]] = true;
    T[i] = i ? T[i - 1] : 0;
    while(F[T[i]]) T[i]++;
    }
    build(root = pt++, 1, n);
    for(int i = 0; i < m; i++)
       B[i].read(i);
    sort(B, B + m);
    int p = 0;
    for(int i = 0; i < n; i++) {
    while(p < m && B[p].l == i) {
    L = B[p].r + 1;
    ans[B[p].p] = query(root, 1, n);
    p++;
    }
    if(i == n - 1 || p >= m) break;
    head[seq[i]] = head[seq[i]]->next;
    L = i + 1; R = head[seq[i]] ? head[seq[i]]->pos : n; v = id[seq[i]];
    modify(root, 1, n);
    }
    for(int i = 0; i < m; i++)
       printf("%d ", ans[i]);
    return 0;
    }

    -------------------------------------------------------------------- 

    3585: mex

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 454  Solved: 232
    [Submit][Status][Discuss]

    Description

      有一个长度为n的数组{a1,a2,...,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。

    Input

      第一行n,m。
      第二行为n个数。
      从第三行开始,每行一个询问l,r。

    Output

      一行一个数,表示每个询问的答案。

    Sample Input

    5 5
    2 1 0 2 1
    3 3
    2 3
    2 4
    1 2
    3 5

    Sample Output

    1
    2
    3
    0
    3

    HINT

    数据规模和约定

      对于100%的数据:

      1<=n,m<=200000

      0<=ai<=109

      1<=l<=r<=n


      对于30%的数据:


      1<=n,m<=1000

    Source

  • 相关阅读:
    想要在控件里面使用触发器,只需要将下面代码填入控件中间即可
    WPF有关控件和模板样式设计的微软官方文档
    XDG0062 XAML 与XDG0008 XAML 错误的解决办法
    在WPF中一种较好的绑定Enums数据方法
    FrameworkElementFactory中的SetBinding与SetValue
    线性表结构:栈
    关于链表的一些问题
    使用Mybatis-Plus的一个坑
    双向链表和双向循环链表
    上下文切换的确切含义了解下
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4708066.html
Copyright © 2011-2022 走看看