[BZOJ4408&&BZOJ4299][FJOI2016 && Codechef]神秘数&&FRBSUM(主席树)
4299: Codechef FRBSUM
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 550 Solved: 351
[Submit][Status][Discuss]Description
数集S的ForbiddenSum定义为无法用S的某个子集(可以为空)的和表示的最小的非负整数。例如,S={1,1,3,7},则它的子集和中包含0(S’=∅),1(S’={1}),2(S’={1,1}),3(S’={3}),4(S’={1,3}),5(S' = {1, 1, 3}),但是它无法得到6。因此S的ForbiddenSum为6。给定一个序列A,你的任务是回答该数列的一些子区间所形成的数集的ForbiddenSum是多少。Input
输入数据的第一行包含一个整数N,表示序列的长度。接下来一行包含N个数,表示给定的序列A(从1标号)。接下来一行包含一个整数M,表示询问的组数。接下来M行,每行一对整数,表示一组询问。Output
对于每组询问,输出一行表示对应的答案。Sample Input
5
1 2 4 9 10
5
1 1
1 2
1 3
1 4
1 5Sample Output
2
4
8
8
8HINT
对于100%的数据,1≤N,M≤100000,1≤A_i≤10^9,1≤A_1+A_2+…+A_N≤10^9。
Source
[Fjoi 2016]神秘数
时间限制:10s 空间限制:128MB
题目描述
一个可重复数字集合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]所构成的可重复数字集合的神秘数。
输入格式
第一行一个整数n,表示数字个数。
第二行n个整数,从1编号。
第三行一个整数m,表示询问个数。
以下m行,每行一对整数l,r,表示一个询问。
输出格式
对于每个询问,输出一行对应的答案。
样例输入
5
1 2 4 9 10
5
1 1
1 2
1 3
1 4
1 5
样例输出
2
4
8
8
8
提示
对于100%的数据点,n,m <= 100000,∑a[i] <= 10^9
题目来源
鸣谢yyh上传
这两题实际上是双倍经验,但我做了两遍且两遍都不会做。。
主席树非常巧妙的应用,对于一个集合S,如果S中的数可以凑出mx,那么如果向集合S中新添加一个数x,若x<=mx+1,那么加入x后S可以凑出0~mx+x的所有数,但如果x>mx+1,则x对扩大可凑出的数的范围没有作用。
这样这题就可做了,设当前已知的一定能凑出来的范围是0~mx(mx初值为0),用权值主席树快速求出区间[l,r]中所有不大于mx+1的数的和作为新的mx,如果发现mx没有增大说明mx+1就是不可凑出的数。
复杂度O(nlog^2n)
BZOJ4299:
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=;
int n,m,nd,l,r,mx,lst,a[N],rt[N],L[N*],R[N*],tot[N*]; void ins(int x,int &y,int l,int r,int k){
y=++nd; L[y]=L[x]; R[y]=R[x]; tot[y]=tot[x]+k;
if (l==r) return; int mid=(l+r)>>;
if (k<=mid) ins(L[x],L[y],l,mid,k); else ins(R[x],R[y],mid+,r,k);
} int que(int x,int y,int l,int r,int k){
if (l==r) return tot[y]-tot[x];
int mid=(l+r)>>;
if (k<=mid) return que(L[x],L[y],l,mid,k);
else return tot[L[y]]-tot[L[x]]+que(R[x],R[y],mid+,r,k);
} int main(){
scanf("%d",&n);
rep(i,,n) scanf("%d",a+i),ins(rt[i-],rt[i],,1e9,a[i]);
for (scanf("%d",&m); m--; ){
scanf("%d%d",&l,&r); mx=lst=;
while (){
mx=que(rt[l-],rt[r],,1e9,mx+);
if (lst==mx) break; lst=mx;
}
printf("%d\n",lst+);
}
return ;
}
BZOJ4408:
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=,M=;
int n,m,l,r,nd,tot,t,ans,a[N],num[N],rt[N],sm[M],ls[M],rs[M]; int find(int x){
int L=,R=tot+;
while (L+<R){
int mid=(L+R)>>;
if (x<num[mid]) R=mid; else L=mid;
}
return L;
} void ins(int y,int &x,int L,int R,int pos,int k){
sm[x=++nd]=sm[y]+k; ls[x]=ls[y]; rs[x]=rs[y];
if (L==R) return;
int mid=(L+R)>>;
if (pos<=mid) ins(ls[y],ls[x],L,mid,pos,k); else ins(rs[y],rs[x],mid+,R,pos,k);
} int que(int l,int r,int k){
int L=,R=tot,mid,ans=; l=rt[l-]; r=rt[r];
while (L<R){
mid=(L+R)>>;
if (k<=mid) R=mid,l=ls[l],r=ls[r];
else L=mid+,ans+=sm[ls[r]]-sm[ls[l]],l=rs[l],r=rs[r];
}
return ans+sm[r]-sm[l];
} int main(){
freopen("bzoj4408.in","r",stdin);
freopen("bzoj4408.out","w",stdout);
scanf("%d",&n);
rep(i,,n) scanf("%d",&a[i]),num[i]=a[i]; n++;
sort(num+,num+n+); tot=unique(num+,num+n+)-num-;
rep(i,,n) a[i]=find(a[i]);
rep(i,,n) ins(rt[i-],rt[i],,tot,a[i],num[a[i]]);
for (scanf("%d",&m); m--; ){
scanf("%d%d",&l,&r);
for (ans=; ; ans=t+){
t=que(l,r,find(ans));
if (t<ans) break;
}
printf("%d\n",ans);
}
return ;
}
[BZOJ4408&&BZOJ4299][FJOI2016 && Codechef]神秘数&&FRBSUM(主席树)的更多相关文章
- 【BZOJ4408】[FJOI2016]神秘数(主席树)
[BZOJ4408][FJOI2016]神秘数(主席树) 题面 BZOJ 洛谷 题解 考虑只有一次询问. 我们把所有数排个序,假设当前可以表示出的最大数是\(x\). 起始\(x=0\). 依次考虑接 ...
- BZOJ4408: [Fjoi 2016]神秘数【主席树好题】
Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = ...
- BZOJ4408 [Fjoi 2016]神秘数 【主席树】
题目链接 BZOJ4408 题解 假如我们已经求出一个集合所能凑出连续数的最大区间\([1,max]\),那么此时答案为\(max + 1\) 那么我们此时加入一个数\(x\),假若\(x > ...
- 洛谷P4587 [FJOI2016]神秘数(主席树)
题面 洛谷 题解 考虑暴力,对于询问中的一段区间\([l,r]\),我们先将其中的数升序排序,假设当前可以表示出\([1,k]\)目前处理\(a_i\),假如\(a_i>k+1\),则答案就是\ ...
- [Bzoj4408]神秘数(主席树)
Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数. 例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = ...
- 220722 T4 求和 /P4587 [FJOI2016]神秘数 (主席树)
好久没打主席树了,都忘了怎么用了...... 假设我们选了一些数能构成[0,x]范围内的所有值,下一个要加的数是k(k<=x+1),那么可以取到[0,x+k]内的所有取值,所以有一种做法: 对于 ...
- 【洛谷4587】 [FJOI2016]神秘数(主席树)
传送门 BZOJ 然而是权限题 洛谷 Solution 发现题目给出的一些规律,emm,如果我们新凑出来的一个数,那么后面一个数一定是\(sum+1\). 于是就可以主席树随便维护了! 代码实现 #i ...
- 【BZOJ4408】[Fjoi 2016]神秘数 主席树神题
[BZOJ4408][Fjoi 2016]神秘数 Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1 ...
- 「FJOI2016」神秘数 解题报告
「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...
随机推荐
- 【HDU】6110 路径交(2017百度之星) 线段树+RMQ-LCA+树链的交
[题目]2017"百度之星"程序设计大赛 - 初赛(A) [题意]给定n个点的带边权树,m条编号1~m的路径,Q次询问编号区间[L,R]所有链的交集的长度.n<=500000 ...
- 20155335俞昆《Java程序设计》第五周总结
# 20155335 <Java程序设计>第五周学习总结 ## 教材学习内容总结 ## 教材学习中的问题和解决过程 对于异常处理,程序中总有意想不到的状况所引发的的错误,Jav ...
- 彻底解决mysql中文乱码
mysql是我们项目中非常常用的数据型数据库.但是因为我们需要在数据库保存中文字符,所以经常遇到数据库乱码情况.下面就来介绍一下如何彻底解决数据库中文乱码情况. 1.中文乱码 1.1.中文乱码 cre ...
- php审计学习:xdcms2.0.8注入
注入点Fields: 注册页面会引用如下方法: $fields 变量是从 $fields=$_POST['fields']; 这里获取, 在代码里没有过滤. 打印 fields 数据查看: 从代码上看 ...
- PHP中的 get_magic_quotes_runtime
get_magic_quotes_runtime() 获得外部文件及数据库资料时是否进行转义 set_magic_quotes_runtime(1); 临时设置获得外部文件及数据库资料时是否进行转义 ...
- 72.xilinx vivado zynq vdma仿真及应用详解(一)
很多人用zynq平台做视频图像开发,但是对vdma了解比较少,上手起来稍微有些困难,我针对这一现象,做了一个基于vivado和modelsim的仿真和应用测试工程,并写篇文章做些介绍,希望能对大家有帮 ...
- nvidia tx1使用记录--基本环境搭建
前言 之前有专门写过一篇nvidia tk1使用记录--基本环境搭建,本以为自己有过tk1的经验后,在tx1上搭建和它一样的环境会轻车熟路,结果却是在nvidia tx1上花的时间居然比tk1还多.我 ...
- udhcpc命令
要使用网络通讯,所以不可避免的要用到dhcp.理想的网络通讯方式是下面3种都要支持: 1,接入已有网络.这便要求可以作为dhcp客户端. 2,作为DHCP服务器,动态分配IP. 简单说下前2种情况. ...
- solr应用
Solr是apache的顶级开源项目,它是使用java开发 ,基于lucene的全文检索服务器.Solr比lucene提供了更多的查询语句,而且它可扩展.可配置,同时它对lucene的性能进行了优化. ...
- 结构体对齐及#pragma详细解释
在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...