bzoj4408: [Fjoi 2016]神秘数

题意:给n个数,定义一段区间神秘数为该区间所有数字通过组合相加所能得到的数的mex,m个询问,对于区间[l,r]询问该区间的神秘树。

如果我们将这段数排序,并且已知前n个数的神秘数为x,即现在凑得的数的区间为[1,x],新加入的数为a,那么不难发现,我们凑得的数又得到了一段区间[a+1,a+x],那么如果a+1<=x,我们就可以拼上这两段,而神秘数变为a+x+1。

也即是说,我们有当前解ans,我们将所有小等ans的数加起来(其实根据前面所推应该是小于,但是写小等不会错,而且对于代码来说更好些,至于为什么不多赘述),如果sigma<ans说明出现了断裂处,即此时ans为答案。否则我们将ans变为sigma+1,继续更新答案。

时间复杂度0(nlogn*P),其中P为常数(当数列为斐波那契时会被卡到极限40)

写代码的时候有一段小插曲。一开始用主席树写的对于每个节点单独累加起来,那样时间复杂度显然不对,实际上直接把每个节点的sum求出来减掉就好了。果然还是太SB啊QAQ

 1 #include<cstdio>
 2 using namespace std;
 3 #define N 100005
 4 int n,m,root[N],ls[100*N],rs[100*N],sum[100*N],cnt,ans,get;
 5 inline int read(){
 6     int x=0,f=1; char a=getchar();
 7     while(a>‘9‘ || a<‘0‘) {if(a==‘-‘) f=-1; a=getchar();}
 8     while(a>=‘0‘ && a<=‘9‘) x=x*10+a-‘0‘,a=getchar();
 9     return x*f;
10 }
11 void inser(int x,int& y,int l,int r,int v){
12     y=++cnt;
13     sum[y]=sum[x]+v;
14     if(l==r) return;
15     ls[y]=ls[x]; rs[y]=rs[x];
16     int mid=(l+r)>>1;
17     if(v>mid) inser(rs[x],rs[y],mid+1,r,v);
18     else inser(ls[x],ls[y],l,mid,v);
19 }
20 int query(int x,int y,int l,int r,int lim){
21     int mid=(l+r)>>1;
22     if(r<=lim) return sum[y]-sum[x];
23     else if(lim<=mid) return query(ls[x],ls[y],l,mid,lim);
24     else return sum[ls[y]]-sum[ls[x]]+query(rs[x],rs[y],mid+1,r,lim);
25 }
26 int main(){
27     n=read();
28     for(int i=1;i<=n;i++) inser(root[i-1],root[i],1,1e9,read());
29     m=read();
30     for(int l,r,i=1;i<=m;i++){
31         l=read(); r=read(); ans=1;
32         while(1){
33             get=query(root[l-1],root[r],1,1e9,ans);
34             if(get<ans) break;
35             ans=get+1;
36         }
37         printf("%d\n",ans);
38     }
39     return 0;
40 }
时间: 2024-10-01 05:27:07

bzoj4408: [Fjoi 2016]神秘数的相关文章

【BZOJ4408】[Fjoi 2016]神秘数 主席树神题

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

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

4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 177  Solved: 128[Submit][Status][Discuss] 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的子集的

【bzoj4408】[Fjoi 2016]神秘数 主席树

题目描述 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1+13 = 1+1+14 = 45 = 4+16 = 4+1+17 = 4+1+1+18无法表示为集合S的子集的和,故集合S的神秘数为8.现给定n个正整数a[1]..a[n],m个询问,每次询问给定一个区间[l,r](l<=r),求由a[l],a[l+1],…,a[r]所构成的可重复数字集合的神秘数. 输入 第一行一个整数n,表示数字个数.第二行n个整数,从1编

●BZOJ BZOJ 4408 [Fjoi 2016]神秘数

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4408 题解: 主席树 首先,对于一些数来说, 如果可以我们可以使得其中的某些数能够拼出 1-ret 那么此时的ANS(神秘数)= ret+1 然后考虑,如果此时存在另一个数小于等于 ANS,(设该数为 x) 则一定可以在原来的1-ret的基础上拼出 1-ret+x 即 ANS 可以更新为 ret+x+1 所以具体的操作就是: 每次查询区间内小于ANS的数的和(SUM),然后如果SUM大于A

bzoj 4408: [Fjoi 2016]神秘数

额,一开始突然想到了如果能表示出连续的二进制位,就可以构造出连续的数了..然后想了一下,不可做2333 于是又走上了扒题解的不归路.. 貌似题解就是推广一下?? 如果能表示出[l,r]那么新加入一个数a,那么可以得到一个新的区间是[l+a,r+a],然后和 [l,r]and[l+a,r+a](and表示取并集)就是现在能表示的区间. 现在我们希望 [l,r]and[l+a,r+a]==[l,r+a] ,这样的话考虑a的加入顺序,显然是应该从小到大的. 而且,在[l,r]and[l+a,r+a]=

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

4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 475  Solved: 287[Submit][Status][Discuss] 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的子集的

FJOI2016 神秘数

题目大意 给定长为$N$一个序列,每次询问一个区间,求最小的不能表示为由区间内若干个(可以是$0$个)数的和的非负整数. 考虑一个可重集合$S$,设抽取$S$中若干个数相加无法得到的最小非负整数为$Ans_S$ 显然$Ans_{\emptyset}=1$ 当加入一个元素$x$时 当$x>Ans_S$时,原先的$Ans_S$仍然无法凑出来,所以答案不变 当$x\leq Ans_S$时,原先的$0,1...Ans_S-1$可表示为$x,x+1...Ans_S-1+x$由于$x\leq Ans_S-1

BZOJ 4408 神秘数

题解同各神犇的方法... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100500 using namespace std; int n,a[maxn],b[maxn],m,l,r,len,tot=0,regis; int ls[maxn*20],rs[maxn*20],sum[maxn*20],root[maxn]; void

[[FJOI2016]神秘数][主席树]

明白之后 5min 就写好了-自闭- 这题的题意是问你 \([L,R]\) 区间的数字不能构成的数字的最小值- 首先考虑 如果 \([1,x]\) 可以被表示 那么加入一个 \(a_i\) 显然 \([1,x+a_i]\) 都可以被表示 有什么好办法呢 当然有 \(O(q * \sum_{i\in[L,R]}{a_i}*[R-L+1])\) (雾) 区间求和问题啥的考虑主席树,首先我不会证明复杂度,是因为我菜/kk 还是一样的套路 讨论 \([1,x]\) 对于区间求 \(\sum_{i\in[