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

【BZOJ4408】[Fjoi 2016]神秘数

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

题解:又是神题啊~

先考虑一种较暴力的方法,我们将[l,r]中的数都拿出来排好序,然后假如我们用前i个数已经能组合出[1,x]的所有数,那么假设设第i+1个数是y,如果y<=x+1,那么我们可以进而组合出[1,x+y]中的所有数;否则,答案就是x+1。

这就需要我们用主席树来维护区间内<=x的所有数的和。然后我们模拟上面的过程。并且容易发现,在这个操作中我们的总和是翻倍式增长的,所以总复杂度只多了一个log。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=100010;
const int inf=1000000000;
int n,m,tot,ans;
struct sag
{
	int ls,rs,sum;
}s[maxn*35];
int rt[maxn];
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
void insert(int x,int &y,int l,int r,int pos)
{
	if(l>r)	return ;
	y=++tot;
	s[y].sum=s[x].sum+pos;
	if(l==r)	return ;
	int mid=l+r>>1;
	if(pos<=mid)	s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos);
	else	s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos);
}
int query(int x,int y,int l,int r,int a)
{
	if(l==r)	return s[y].sum-s[x].sum;
	int mid=l+r>>1;
	if(a<=mid)	return query(s[x].ls,s[y].ls,l,mid,a);
	else	return s[s[y].ls].sum-s[s[x].ls].sum+query(s[x].rs,s[y].rs,mid+1,r,a);
}
int main()
{
	n=rd();
	int i,a,b,tmp;
	for(i=1;i<=n;i++)	a=rd(),insert(rt[i-1],rt[i],0,inf,a);
	m=rd();
	for(i=1;i<=m;i++)
	{
		a=rd(),b=rd(),ans=1;
		while(1)
		{
			tmp=query(rt[a-1],rt[b],0,inf,ans);
			if(tmp<ans)	break;
			ans=tmp+1;
		}
		printf("%d\n",ans);
	}
	return 0;
}
时间: 2024-08-24 00:51:13

【BZOJ4408】[Fjoi 2016]神秘数 主席树神题的相关文章

【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编

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的数加起来(其实根据前面所推应该是小于,但是写小等不会错,而且对于代码来说更好些,

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的子集的

●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]=

[[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[

【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的子集的

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质

小任老师解读 2016最新软考真题,23号QQ群直播546330070

时间:11月23号晚8点-9点30. 地点:QQ群直播546330070 分享老师:小任老师 河北师范大学软件学院优秀讲师,十年软考辅导备考专家,高级项目经理,系统分析师 分享内容:2016最新软考真题解读 分享大纲: 2016年11月23号晚上8点准时开始 课前活动:到场学员晚7:58开始签到,前10名签到学员奖励100学分. 晚8:00-8:15,2016年下半年系统集成真题介绍   (15分钟) 晚8:15-9:00,2016年下半年系统集成上.下午真题解析(45分钟) 晚9:00-9:2