[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 1256 画8 (找规律)
题目链接 Problem Description 谁画8画的好,画的快,今后就发的快,学业发达,事业发达,祝大家发,发,发. Input 输入的第一行为一个整数N,表示后面有N组数据. 每组数据中 ...
- Spring Data JPA笔记
1. Spring Data JPA是什么 Spring Data JPA是Spring Data大家族中的一员,它对对持久层做了简化,用户只需要声明方法的接口,不需要实现该接口,Spring Dat ...
- Shader -> Photoshop图层混合模式计算公式大全
Photoshop图层混合模式计算公式大全 混合模式可以将两个图层的色彩值紧密结合在一起,从而创造出大量的效果,在这些效果的背后实际是一些简单的数学公式在起作用. 下面是photoshop cs2中所 ...
- 自己看之区间DP
//菜鸡制作,看的时候可能三目运算符略烦;;; 区间DP入门题:Brackets 地址:http://59.77.139.92/Problem.jsp?pid=1463 分析(对区间DP的代码原理进行 ...
- python基本数据类型list,tuple,set,dict用法以及遍历方法
1.list类型 类似于java的list类型,数据集合,可以追加元素与删除元素. 遍历list可以用下标进行遍历,也可以用迭代器遍历list集合 建立list的时候用[]括号 import sys ...
- 2-Python基础语法-内存管理-运算符-程序控制
目录 1 Python 基础语法 1.1 注释 1.2 缩进 1.3 续行 1.4 标识符 1.5 转义序列 1.6 数字 1.7 字符串 1.8 其他 2 Python 运算符 2.1 赋值运算符 ...
- 浅析busybox如何集成到openwrt
背景 近日添加了一个包到openwrt中,在此过程中又对openwrt多了一些认识 这个包本身自带了kconfig,可直接在这个包里面执行make menuconfig进行配置,然后执行make 但要 ...
- memcached安装【转】
1.安装依赖软件 # yum -y install libevent libevent-devel perl-Test-Harness perl-Time-HiRes perl-TermReadKey ...
- 修改vs17中的cordova模板
因为visual studio 2017创建的默认cordova-ios的版本自动编译带有swift语言的插件会出现异常,cordova-ios升级到4.3.1,并且配置build.json能解决问题 ...
- acm专题---拓扑排序+优先队列
struct node{ int id; int cnt; node(int _id,int _cnt):id(_id),cnt(_cnt){} bool operator<(node a) c ...