博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[FJOI2016]神秘数(脑洞+可持久化)
阅读量:5061 次
发布时间:2019-06-12

本文共 1270 字,大约阅读时间需要 4 分钟。

题目描述

一个可重复数字集合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个询问,每次询问给定一个区间,求由a[l],a[l+1],…,a[r]所构成的可重复数字集合的神秘数。

题解

加入我们查询的区间为l-r。

我们先查询有几个1,然后发现有k个,那么然后我们再查询1-k+1有多少数,如果大于等于k+1的话,那么1到k+1都能表出。

重复这个过程即可,最多跳log次。

代码

#include
#include
#define N 100002using namespace std;typedef long long ll;const int maxn=1e9;ll tr[N*32],a[N];int L[N*32],R[N*32],tot,n,m,T[N];inline int rd(){ int x=0;char c=getchar();bool f=0; while(!isdigit(c)){
if(c=='-')f=1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();} return f?-x:x;}void ins(int &cnt,int pre,int l,int r,ll x){ cnt=++tot; tr[cnt]=tr[pre]+x;L[cnt]=L[pre];R[cnt]=R[pre]; if(l==r)return; int mid=(l+r)>>1; if(mid>=x)ins(L[cnt],L[pre],l,mid,x); else ins(R[cnt],R[pre],mid+1,r,x); }ll query(int cnt,int pre,int l,int r,ll x){// cout<
<<" "<
<<" "<
<<" "<
<<" "<
<<" "<
<
>1; if(mid

转载于:https://www.cnblogs.com/ZH-comld/p/10188448.html

你可能感兴趣的文章
01入门
查看>>
python正则表达式
查看>>
嵌套循环连接(nested loops join)原理
查看>>
shell统计特征数量
查看>>
复习文件操作
查看>>
C#Hashtable与Dictionary性能
查看>>
10个让你忘记 Flash 的 HTML5 应用演示
查看>>
8个Python面试必考的题目,小编也被坑过 ToT
查看>>
SQL Server 使用作业设置定时任务之一(转载)
查看>>
centos 图形界面和命令行界面切换(转载)
查看>>
Maven启用代理访问
查看>>
Primary definition
查看>>
第二阶段冲刺-01
查看>>
BZOJ1045 HAOI2008 糖果传递
查看>>
发送请求时params和data的区别
查看>>
JavaScript 克隆数组
查看>>
eggs
查看>>
一步步学习微软InfoPath2010和SP2010--第七章节--从SP列表和业务数据连接接收数据(4)--外部项目选取器和业务数据连接...
查看>>
如何增强你的SharePoint 团队网站首页
查看>>
FZU 1914 Funny Positive Sequence(线性算法)
查看>>