题目大意:给定一个长度为$n$的正整数序列$a_i$,$m$次询问,每次询问$[l,r]$,求最小的无法表示成$a_l,a_{l+1},\ldots,a_r$的子集之和的正整数。

数据范围:$1\leq l\leq r\leq n\leq 10^5,1\leq m\leq 10^5,\sum a_i\leq 10^9$


(FJOI考Codechef原题???)

这个套路之前学校训练的时候也遇到过,这里又遇到了。。。

我们考虑对于一组询问如何计算。

首先,我们知道$[1,0]$是肯定可以表示出来的(为了方便表示就这样写了)

可以像数学归纳法那样递推,先把所有数从小到大排序,假设$[1,x]$被计算出都是可以表示的,现在又有了一个新的数$v$。

若$v>x+1$,那么$x+1$还是无法表示出来,还是只有$[1,x]$是可以的。

若$v\leq x+1$,那么$[1,x+v]$都是可以表示的。


根据这个规律,我们这样考虑。

设$s_0=0$,每次递推这样做($i=0,1,2,3,\ldots$)。

计算区间中$\leq s_i+1$的数之和,设为$s_{i+1}$。

反复进行,直到$s_i=s_{i+1}$,也就是无法再扩展这个区间了,答案就是$s_i+1$。

(感性理解一下,应该就是对的)

但是我们需要这样递推多少次呢?

我们发现,$s_i$增长最慢的情况就是$s_0=0,s_1=1,s_2=2,s_3=3,s_4=5,s_5=8,\ldots$,就是斐波那契数列,所以是指数级别增长的,所以在$\log(\sum a_i)$次以内就会停止。

每次计算$\leq s_i+1$的数之和的时候,可以用从小到大将数加入主席树,然后二分一下每次在哪个线段树中计算$[l,r]$中的和就可以了。

时间复杂度为$O(n\log n\log(\sum a_i))$

 #include<bits/stdc++.h>
#define Rint register int
using namespace std;
const int N = ;
int n, m, a[N], id[N], root[N], seg[N << ], ls[N << ], rs[N << ], cnt;
inline void pushup(int x){seg[x] = seg[ls[x]] + seg[rs[x]];}
inline void change(int &now, int pre, int L, int R, int pos, int val){
now = ++ cnt; seg[now] = seg[pre]; ls[now] = ls[pre]; rs[now] = rs[pre];
if(L == R){
seg[now] = val;
return;
}
int mid = L + R >> ;
if(pos <= mid) change(ls[now], ls[pre], L, mid, pos, val);
else change(rs[now], rs[pre], mid + , R, pos, val);
pushup(now);
}
inline int query(int x, int L, int R, int l, int r){
if(l <= L && R <= r) return seg[x];
int mid = L + R >> , ans = ;
if(l <= mid) ans += query(ls[x], L, mid, l, r);
if(mid < r) ans += query(rs[x], mid + , R, l, r);
return ans;
}
inline int calc(int l, int r, int v){
int left = , right = n, mid, ans;
while(left <= right){
mid = left + right >> ;
if(a[id[mid]] <= v) ans = mid, left = mid + ;
else right = mid - ;
}
return query(root[ans], , n, l, r);
}
int main(){
scanf("%d", &n);
for(Rint i = ;i <= n;i ++) scanf("%d", a + i), id[i] = i;
sort(id + , id + n + , [](int x, int y) -> bool {return a[x] < a[y];});
for(Rint i = ;i <= n;i ++)
change(root[i], root[i - ], , n, id[i], a[id[i]]);
scanf("%d", &m);
while(m --){
int l, r, s = , tmp = ;
scanf("%d%d", &l, &r);
while(true){
tmp = calc(l, r, s + );
if(s == tmp) break;
s = tmp;
}
printf("%d\n", s + );
}
}

Luogu4587

Luogu4587 [FJOI2016]神秘数的更多相关文章

  1. 【BZOJ4408】[FJOI2016]神秘数(主席树)

    [BZOJ4408][FJOI2016]神秘数(主席树) 题面 BZOJ 洛谷 题解 考虑只有一次询问. 我们把所有数排个序,假设当前可以表示出的最大数是\(x\). 起始\(x=0\). 依次考虑接 ...

  2. 【LG4587】[FJOI2016]神秘数

    [LG4587][FJOI2016]神秘数 题面 洛谷 题解 首先我们想一想暴力怎么做 对于一段区间\([l,r]\) 我们先将它之间的数升序排序 从左往右扫, 设当前我们可以表示出的数为\([1,x ...

  3. (bzoj4408)[FJOI2016]神秘数(可持久化线段树)

    (bzoj4408)[FJOI2016]神秘数(可持久化线段树) bzoj luogu 对于一个区间的数,排序之后从左到右每一个数扫 如果扫到某个数a时已经证明了前面的数能表示[1,x],那么分情况: ...

  4. [bzoj4408][Fjoi2016]神秘数

    Description 一个可重复数字集合$S$的神秘数定义为最小的不能被$S$的子集的和表示的正整数. 例如$S={1,1,1,4,13}$, $1=1$, $2=1+1$, $3=1+1+1$, ...

  5. [FJOI2016]神秘数(脑洞+可持久化)

    题目描述 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = 4+1 6 = ...

  6. Luogu P4587 [FJOI2016]神秘数

    一道好冷门的好题啊,算是对于一个小结论和数据结构的一点考验吧 首先看完题目我们发现要从这个神秘数的性质入手,我们观察or手玩可得: 如果有\(x\)个\(1\),那么\([1,x]\)都是可以表示出来 ...

  7. BZOJ4299 & CC FRBSUM:ForbiddenSum & BZOJ4408 & 洛谷4587 & LOJ2174:[FJOI2016]神秘数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4299 https://www.lydsy.com/JudgeOnline/problem.php? ...

  8. BZOJ 4408 FJOI2016 神秘数 可持久化线段树

    Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1+13 = 1+1+14 = 45 = 4+16 ...

  9. 洛谷 P4587 [FJOI2016]神秘数

    大鸽子 llmmkk 正在补8.3号咕掉的题 时隔两个月,再看到这道题,我又是一脸懵,这种思维的培养太重要了 链接: P4587 题意: 给出 \(n\) 个点的序列,\(m\) 次询问区间神秘数. ...

随机推荐

  1. 【原创】大数据基础之Zookeeper(1)介绍、安装及使用

    zookeeper3.4.11 http://zookeeper.apache.org/ 一 简介 ZooKeeper is a centralized service for maintaining ...

  2. 【原创】Linux基础之上传下载

    1 rz sz 安装 yum install -y lrzsz 上传 rz ,对话框操作 下载 sz $filename 注意:rz不能上传大于4g的文件,此时可以改为scp或sftp上传,其中sft ...

  3. POJ1321 棋盘问题(简单搜索)

    题意: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放 ...

  4. P2866 [USACO06NOV]糟糕的一天Bad Hair Day--单调栈

    P2866 [USACO06NOV]糟糕的一天Bad Hair Day 题意翻译 农夫约翰有N (N \leq 80000)N(N≤80000)头奶牛正在过乱头发节.每一头牛都站在同一排面朝东方,而且 ...

  5. cc.Node 的坐标空间与ACTION的学习

    1.创建二维的向量坐标 //创建向量坐标方法一 let new_pos1 = new cc.Vec2(100, 100); //创建向量坐标方法二 let new_pos2 = cc.v2(200, ...

  6. jmeter测试wordpress使用base64进行鉴权

    1.下载插件 对密码进行加密 2.安装插件 3.使用插件 4.使用base64对上面获取到的密码进行二次加密 echo -n "用户:密码" | base64 将以上命令键入lin ...

  7. mac os app 开发

    macOS 新手开发:第 1 部分 macOS 新手开发:第 2 部分 macOS 新手开发:第 3 部分

  8. 怎样设置高效的IIS

    适用的IIS版本:IIS 7.0, IIS 7.5, IIS 8.0 适用的Windows版本:Windows Server 2008, Windows Server 2008 R2, Windows ...

  9. SQL反模式学习笔记19 使用*号,隐式的列

    目标:减少输入 反模式:捷径会让你迷失方向 使用通配符和未命名的列能够达到减少输入的目的,但是这个习惯会带来一些危害. 1.破坏代码重构:增加一列后,使用隐式的Insert插入语句报错: 2.查询中使 ...

  10. C# SortedDictionary以及SortedList的浅谈

    msdn叙述:The SortedDictionary<TKey, TValue> generic class is a binary search tree with O(log n) ...