Description

一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数。例如S={1,1,1,4,13},
1 = 1
2 = 1+1
3 = 1+1+1
4 = 4
5 = 4+1
6 = 4+1+1
7 = 4+1+1+1
8无法表示为集合S的子集的和,故集合S的神秘数为8。
现给定n个正整数a[1]..a[n],m个询问,每次询问给定一个区间[l,r](l<=r),求由a[l],a[l+1],…,a[r]所构成的可重复数字集合的神秘数。

Input

第一行一个整数n,表示数字个数。
第二行n个整数,从1编号。
第三行一个整数m,表示询问个数。
以下m行,每行一对整数l,r,表示一个询问。

Output

对于每个询问,输出一行对应的答案。

Sample Input

5
1 2 4 9 10
5
1 1
1 2
1 3
1 4
1 5

Sample Output

2
4
8
8
8

HINT

对于100%的数据点,n,m <= 100000,∑a[i] <= 10^9

题意极为简洁。。。。

可以发现这个题需要分析一些性质来判断一个数是否可以被凑出来。一个数被凑出来的时候一定不会用到大于它的数字,只可能会用到小于它的数字。

问题看起来很无序,那么找到一个考虑的顺序,把询问区间内所有的数字从小到大开始考虑。首先看有没有1,如果有,那么1就可以凑出来,同时可以发现如果有x个1,那么1~x都可以凑出来。那么考虑1~x范围内的所有数字,你可发现任何一个非1的数字都可以使我们可以连续表达的数字区间增大了(脑补一个移动的窗口),1~x区间内能表示出的最大数字就是 x+(区间内小于等于x的最大值)。仔细一想这正是一个同构子问题!

每一次都这样做,我们最多会扩大几次考虑范围呢?不难发现只要还有答案成立,这一次扩大之后的考虑范围至少是上一次的两倍,所以最多也就log级别。

于是我们只需要维护区间内小于等于某个数字的和就可以了,开心上一发主席树板子。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int MAXN=; int N,M,AA[MAXN],rank[MAXN],tot;
struct persistable_segment_tree{
static const int maxn=;
static const int maxm=;
int root[maxm],np,lc[maxn],rc[maxn],sum[maxn];
persistable_segment_tree(){ np=; }
void pushup(int now){ sum[now]=sum[lc[now]]+sum[rc[now]]; }
void build(int &now,int L,int R){
now=++np,lc[now]=rc[now]=sum[now]=;
if(L==R) return;
int m=L+R>>;
build(lc[now],L,m); build(rc[now],m+,R);
}
int copynode(int now){
np++,lc[np]=lc[now],rc[np]=rc[now],sum[np]=sum[now];
return np;
}
void update(int &now,int L,int R,int pos,int v){
now=copynode(now);
if(L==R){ sum[now]+=v; return; }
int m=L+R>>;
if(pos<=m) update(lc[now],L,m,pos,v);
else update(rc[now],m+,R,pos,v);
pushup(now);
}
int query(int xx,int yy,int L,int R,int A,int B){
if(A<=L&&R<=B) return sum[yy]-sum[xx];
int m=L+R>>;
if(B<=m) return query(lc[xx],lc[yy],L,m,A,B);
if(A>m) return query(rc[xx],rc[yy],m+,R,A,B);
return query(lc[xx],lc[yy],L,m,A,B)+query(rc[xx],rc[yy],m+,R,A,B);
}
}st; void data_in()
{
scanf("%d",&N);
for(int i=;i<=N;i++) scanf("%d",&AA[i]);
scanf("%d",&M);
}
void work()
{
memcpy(rank,AA,sizeof(AA));
sort(rank+,rank+N+);
tot=unique(rank+,rank+N+)-rank;
st.build(st.root[],,tot-);
for(int i=;i<=N;i++){
st.root[i]=st.root[i-];
st.update(st.root[i],,tot-,lower_bound(rank+,rank+tot,AA[i])-rank,AA[i]);
}
int l,r,pos,ans,tmp;
for(int i=;i<=M;i++){
scanf("%d%d",&l,&r);
pos=upper_bound(rank+,rank+tot,)-rank-,ans=;
while(pos){
tmp=st.query(st.root[l-],st.root[r],,tot-,,pos);
if(tmp<ans) break;
ans=tmp+;
if(pos==tot-) break;
pos=upper_bound(rank+,rank+tot,ans)-rank-;
}
printf("%d\n",ans);
}
}
int main()
{
data_in();
work();
return ;
}

BZOJ 4408 FJOI2016 神秘数 可持久化线段树的更多相关文章

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

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

  2. Bzoj 4408: [Fjoi 2016]神秘数 可持久化线段树,神题

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 177  Solved: 128[Submit][Status ...

  3. BZOJ 4408: [Fjoi 2016]神秘数 可持久化线段树

    4408: [Fjoi 2016]神秘数 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4408 Description 一个可重复数字集 ...

  4. 【BZOJ-4408】神秘数 可持久化线段树

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 475  Solved: 287[Submit][Status ...

  5. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  6. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  7. 51Nod 1175 区间中第K大的数 (可持久化线段树+离散)

    1175 区间中第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题   一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有 ...

  8. BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)

    首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...

  9. bzoj 4504: K个串 可持久化线段树+堆

    题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...

随机推荐

  1. 优雅的QSignleton (四) 通过属性器实现MonoSingleton

      大家都出去过周六了,而我却在家写代码T.T...   接下来介绍通过属性器实现MonoSingleton. 代码如下: MonoSingletonProperty.cs namespace QFr ...

  2. Python基础—15-正则表达式

    正则表达式 应用场景 特定规律字符串的查找替换切割等 邮箱格式.URL.IP等的校验 爬虫项目中,特定内容的提取 使用原则 只要是能够使用字符串函数解决的问题,就不要使用正则 正则的效率较低,还会降低 ...

  3. c#实现的udt

    不多说,当前具备基本通信,是从java版本转换过来的.可以参阅. 项目地址 https://github.com/jinyuttt/netudt.git

  4. session和cookie的介绍

    1.将cookie,session之前,还是先说说http协议 http协议是基于TCP/UDP之上的应用层一个标准 请求,响应的模式.是你必须先请求到一个服务端之后,服务端才会响应到你.他是不会无缘 ...

  5. Vue组件通讯黑科技

    Vue组件通讯 组件可谓是 Vue框架的最有特色之一, 可以将一大块拆分为小零件最后组装起来.这样的好处易于维护.扩展和复用等. 提到 Vue的组件, 相必大家对Vue组件之间的数据流并不陌生.最常规 ...

  6. zepto 基础知识(5)

    81.width width() 类型:number width(value) 类型:self width(function(index,oldWidth){....}) 类型:self 获取对象集合 ...

  7. PostgreSQL异步主从流复制搭建

    1 总体规划   Master库 Slave库 操作系统 CentOS Linux release 7.5.1804 CentOS Linux release 7.5.1804 处理器 1 1 内存 ...

  8. 【操作系统作业—lab1】linux shell脚本 遍历目标文件夹和所有文件 | 包括特殊字符文件名的处理

    要求:写一个linux bash脚本来查看目标文件夹下所有的file和directory,并且打印出他们的绝对路径. 运行command:./myDir.sh  input_path  output_ ...

  9. 003---random随机数模块

    import random # 随机数(0-1) print(random.random()) # 随机整数, 包含尾巴 print(random.randint(-1, 2)) # 不包含尾巴 pr ...

  10. Hadoop学习(一) Hadoop是什么

    Hadoop是什么? Hadoop是一个开发和运行处理大规模数据的软件平台,是Appach的一个用Java语言实现开源软件框架,实现在大量计算机组成的集群中对海量数据进行分布式计算. Hadoop框架 ...