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

    [FJOI2016]神秘数

    题目

    仍然自己上网搜~~~~~~

    思路

    不得不说这题很~~~
    规律,永远是宇宙的终极杀器
    我们考虑当前的集合可以表示的数的值域为 ([1..Max])
    这段区间是连续的
    为什么我们只考虑从 (1) 开始连续的区间?
    因为这样我们可以知道答案显然为 (Max + 1)
    因为 (Max + 1) 是最小的不能被表示的数
    ······
    废话!!!
    其实我们可以反过来想,如果我猜想当前答案可能为 (ans)
    然后验证它是不是答案
    那么当前集合我们是不需要考虑比 (ans) 大的数的
    也就是说当前集合比 (ans) 小的数能拼成的所有数中有没有 (ans) 就是判定关键
    可是我怎么知道它怎么能拼出!!!
    如果它能拼出的数的区间是连续的那就好了

    其实我们注意到,它的区间即使不是连续的,也分成了几块连续的段
    那么我们可以从小(即 (1))到大猜一个 (ans)
    然后查询区间中小于等于 (ans) 的数之和(注:因为这个区间能表示的数是连续的,所以上限是这些数之和,判上限就好了)
    若这个和为 (s)
    如果 (s leq ans) ,那么 (ans) 不能被表示,因为从小到大,所以它就是答案
    否则,我们得重新猜 (ans)
    (ans = s + 1) ?!!!
    这样时间就有保证了
    (O(m log n log{sum a_i}))

    (Code)

    #include<cstdio>
    using namespace std;
    
    const int N = 1e5 , Len = 1e9;
    int n , m , a[N + 5] , rt[N + 5] , size;
    
    struct segment{
    	int ls , rs , sum;
    }seg[(N << 5) + 5];
    
    inline int update(int x , int l , int r , int v)
    {
    	int o = ++size;
    	seg[o] = seg[x] , seg[o].sum += v;
    	if (l == r) return o;
    	int mid = (l + r) >> 1;
    	if (v <= mid) seg[o].ls = update(seg[x].ls , l , mid , v);
    	else seg[o].rs = update(seg[x].rs , mid + 1 , r , v);
    	return o;
    }
    
    inline int query(int u , int v , int l , int r , int val)
    {
    	if (r <= val) return seg[v].sum - seg[u].sum;
    	int mid = (l + r) >> 1 , res = 0;
    	res += query(seg[u].ls , seg[v].ls , l , mid , val);
    	if (val > mid) res += query(seg[u].rs , seg[v].rs , mid + 1 , r , val);
    	return res;
    }
    
    int main()
    {
    	scanf("%d" , &n);
    	for(register int i = 1; i <= n; i++) scanf("%d" , &a[i]) , rt[i] = update(rt[i - 1] , 1 , Len , a[i]);
    	scanf("%d" , &m);
    	int l , r;
    	for(; m; m--)
    	{
    		scanf("%d%d" , &l , &r);
    		int ans = 1 , s = 0;
    		while (1)
    		{
    			s = query(rt[l - 1] , rt[r] , 1 , Len , ans);
    			if (s < ans) {printf("%d
    " , ans); break;}
    			else ans = s + 1;
    		}
    	}
    }
    
  • 相关阅读:
    python3笔记-列表
    python3笔记-字典
    MD侧滑
    SnackBar使用
    TextIInputLayout使用
    Toolbar与SearchView
    Palette使用
    TabLayout使用
    沉浸式-体验
    沉浸式-兼容优化
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13448936.html
Copyright © 2011-2022 走看看