zoukankan      html  css  js  c++  java
  • 【LG4587】[FJOI2016]神秘数

    【LG4587】[FJOI2016]神秘数

    题面

    洛谷

    题解

    首先我们想一想暴力怎么做

    对于一段区间([l,r])

    我们先将它之间的数升序排序

    从左往右扫,

    设当前我们可以表示出的数为([1,x]),待插入的数为(a_i)

    会有下面两种情况:

    1.(a_i> x+1)时,(x+1)肯定表示不出来(ans=x+1)

    2.(a_ileq x+1)时,值域变为([1,x+a_i]),继续扫

    那么我们暴力的复杂度为(O(nmlogn))

    考虑怎么优化这个过程

    还是用刚才的思路

    设当前值域([1,x])

    (ans=x+1)

    若小于等于(ans)的数的和(resgeq ans),则一定有未选的且小于等于(ans)的数,

    (ans=res+1)即可。

    反之说明答案就是(ans),直接(break)

    因为有(sum a_ileq 10^9),用主席树维护

    所以复杂度(O(m(logn)(logsum a_i)))

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    inline int gi() { 
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    }
    const int MAX_N = 1e5 + 5; 
    const int INF = 1e9; 
    struct Node { int ls, rs, v; } t[MAX_N << 5]; 
    int rt[MAX_N], tot = 0; 
    void insert(int &o, int p, int l, int r, int pos, int v) { 
        o = ++tot, t[o] = t[p], t[o].v += v; 
        if (l == r) return ; 
        int mid = (l + r) >> 1; 
        if (pos <= mid) insert(t[o].ls, t[p].ls, l, mid, pos, v); 
        else insert(t[o].rs, t[p].rs, mid + 1, r, pos, v); 
    } 
    int query(int v, int u, int l, int r, int ql, int qr) { 
        if (ql <= l && r <= qr) return t[u].v - t[v].v; 
        int mid = (l + r) >> 1, res = 0; 
        if (ql <= mid) res += query(t[v].ls, t[u].ls, l, mid, ql, qr); 
        if (qr > mid) res += query(t[v].rs, t[u].rs, mid + 1, r, ql, qr); 
        return res; 
    } 
    int N, a[MAX_N]; 
    int main () { 
        N = gi(); for (int i = 1; i <= N; i++) a[i] = gi(); 
        for (int i = 1; i <= N; i++) insert(rt[i], rt[i - 1], 1, INF, a[i], a[i]); 
        int M = gi();
        while (M--) { 
            int l = gi(), r = gi(), ans = 1; 
            for (;;) { 
                int res = query(rt[l - 1], rt[r], 1, INF, 1, ans); 
                if (res >= ans) ans = res + 1; 
                else break; 
            } 
            printf("%d
    ", ans); 
        } 
        return 0; 
    } 
    
  • 相关阅读:
    lunix查询jdk安装路径
    (四)爬虫之动态网页
    (二)爬虫之数据提取
    图及其衍生算法(Graphs and graph algorithms)
    树及其衍生算法(Trees and tree algorithms)
    数据结构之链表(Linked list)
    查找与排序算法(Searching adn Sorting)
    数据结构之双端队列(Deque)
    数据结构之队列(Queue)
    多个git账号的SSH配置
  • 原文地址:https://www.cnblogs.com/heyujun/p/10279103.html
Copyright © 2011-2022 走看看