[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背包可以求出更多的东西,就 ...
随机推荐
- 【BZOJ】1572: [Usaco2009 Open]工作安排Job
[题意]给定n项工作的截止时间和价值,每项工作需要1单位时间完成,求最大价值.n<=10^5. [算法]贪心+堆 [题解] 如果是访问到x时将d[x]前的点从价值最大的能加就加是错误的贪心,因为 ...
- 【CodeForces】914 H. Ember and Storm's Tree Game 动态规划+排列组合
[题目]H. Ember and Storm's Tree Game [题意]Zsnuoの博客 [算法]动态规划+排列组合 [题解]题目本身其实并不难,但是大量干扰因素让题目显得很神秘. 参考:Zsn ...
- Redis笔记之常用命令
keys keys用来获取符合指定规则的键,keys的语法规则如下: keys <pattern> 比如最简单的全等匹配,下面这个命令只会匹配键值完全等于foo的: 127.0.0.1:6 ...
- Masquerade strikes back Gym - 101911D(补题) 数学
https://vjudge.net/problem/Gym-101911D 具体思路: 对于每一个数,假设当前的数是10 分解 4次,首先 1 10 这是一对,然后下一次就记录 10 1,这样的话直 ...
- THINKPHP简单商品查询项目
代码:http://files.cnblogs.com/files/wordblog/test.zip
- python开发规范(转载)
转载自http://www.cnblogs.com/wangcp-2014/p/4838952.html 目录 代码布局 1.1 缩进 1.2 表达式和语句中的空格 1.3 行的最大长度 1.4 空行 ...
- Freemaker如何遍历key为non-string类型的map?
(一) 前置知识 Freemaker默认配置下会使用SimpleHash去包装后台传递的hashmap,下段摘抄自官方reference 同样,当你传递进去一个hashmap实例时,会替换为一个sim ...
- opencv配置过程 (cmake,vs2013,qt 5.4)
平台及软件: Windows 7 X86 Visual Studio 2013 OpenCV3.0.0 Cmake3.3 1.下载Windows下的安装文件OpenCV-3.0.0.exe,解压,选择 ...
- LINUX内核中的机制OOM
[概念] LINUX内核中有一个机制叫做OOM killer(Out Of Memery killer) 该机制监控内存占用过大,尤其是瞬间消耗大量内存的进程, 为了防止内存被耗尽,所以OOM kil ...
- MYSQL三种安装方式--二进制包安装
1. 把二进制包下载到/usr/local/src下 2. 如果是tar.gz包,则使用tar zxvf 进行解压 如果是tar包,则可以使用tar xvf 进行解压 3. $ mv mysql-5. ...