Luogu P4587 [FJOI2016]神秘数
一道好冷门的好题啊,算是对于一个小结论和数据结构的一点考验吧
首先看完题目我们发现要从这个神秘数的性质入手,我们观察or手玩可得:
- 如果有\(x\)个\(1\),那么\([1,x]\)都是可以表示出来的
- 如果我此时加入的数\(y>x\),那么这个数无法被表示,因此便为答案
- 如果我此时加入的数\(y\le x\),那么这个数可以被表示,并且可以表示的区间变成了\([1,x+y]\)
重复以上过程,肯定可以得出答案
但这样对于每一次询问都要进行一次排序,时间复杂度为\(O(nm\ logn)\),肯定跑不过去的。我们换一种想法,假设我此时已经表示出了\([1,x]\),那么我统计一下在区间\([l,r]\)中所有小于等于\(x+1\)的数的和\(s\)
若\(s\ge x+1\),说明此时必定还存在更大的组合方案,于是可以表示的区间变为\([1,s]\)
再考虑上述的核心过程:统计一段区间内小于等于某个数的数的和
直接主席树即可,把值域线段树的点权改为数的和即可,查询的时候还是分左右子树查找
由于查询之后每次的答案扩大至少一倍,因此总复杂度\(O(m\ log^2n)\)
CODE
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=100005;
struct President_tree
{
int ch[2],sum;
}node[N*20];
int n,m,q,rt[N],a[N],b[N],tot,l,r;
inline char tc(void)
{
static char fl[100000],*A=fl,*B=fl;
return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(int x)
{
if (x>9) write(x/10);
putchar(x%10+'0');
}
inline int find(int x)
{
int l=1,r=m,mid,res;
while (l<=r)
{
mid=l+r>>1;
if (b[mid]<=x) res=mid,l=mid+1; else r=mid-1;
}
return res;
}
inline void build(int &now,int l,int r)
{
if (!now) now=++tot; if (l==r) return; int mid=l+r>>1;
build(node[now].ch[0],l,mid); build(node[now].ch[1],mid+1,r);
}
inline int insert(int lst,int l,int r,int id,int x)
{
int now=++tot; node[now]=node[lst]; node[now].sum+=x;
if (l==r) return now; int mid=l+r>>1;
if (id<=mid) node[now].ch[0]=insert(node[lst].ch[0],l,mid,id,x);
else node[now].ch[1]=insert(node[lst].ch[1],mid+1,r,id,x); return now;
}
inline int query(int lst,int now,int l,int r,int beg,int end)
{
int mid=l+r>>1,res=0;
if (l>=beg&&r<=end) return node[now].sum-node[lst].sum;
if (beg<=mid) res+=query(node[lst].ch[0],node[now].ch[0],l,mid,beg,end);
if (end>mid) res+=query(node[lst].ch[1],node[now].ch[1],mid+1,r,beg,end);
return res;
}
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
register int i; read(n);
for (i=1;i<=n;++i)
read(a[i]),b[i]=a[i]; read(q);
sort(b+1,b+n+1); m=unique(b+1,b+n+1)-b-1; build(rt[0],1,m);
for (i=1;i<=n;++i)
{
int x=find(a[i]);
rt[i]=insert(rt[i-1],1,m,x,a[i]);
}
for (i=1;i<=q;++i)
{
read(l); read(r); int ans=1;
for (;;)
{
int x=find(ans),s=query(rt[l-1],rt[r],1,m,1,x);
if (s>=ans) ans=s+1; else break;
}
write(ans); putchar('\n');
}
return 0;
}
Luogu P4587 [FJOI2016]神秘数的更多相关文章
- LUOGU P4587 [FJOI2016]神秘数(主席树)
传送门 解题思路 如果区间内没有\(1\),那么答案就为\(1\),从这一点继续归纳.如果区间内有\(x\)个\(1\),设区间内\([2,x+1]\)的和为\(sum\),如果\(sum=0\),那 ...
- 洛谷 P4587 [FJOI2016]神秘数
大鸽子 llmmkk 正在补8.3号咕掉的题 时隔两个月,再看到这道题,我又是一脸懵,这种思维的培养太重要了 链接: P4587 题意: 给出 \(n\) 个点的序列,\(m\) 次询问区间神秘数. ...
- 洛谷P4587 [FJOI2016]神秘数(主席树)
题面 洛谷 题解 考虑暴力,对于询问中的一段区间\([l,r]\),我们先将其中的数升序排序,假设当前可以表示出\([1,k]\)目前处理\(a_i\),假如\(a_i>k+1\),则答案就是\ ...
- P4587 [FJOI2016]神秘数(主席树)
题意:给出1e5个数 查询l,r区间内第一个不能被表示的数 比如1,2,4可以用子集的和表示出[1,7] 所以第一个不能被表示的是8 题解:先考虑暴力的做法 把这个区间内的数字按从小到大排序后 从前往 ...
- 220722 T4 求和 /P4587 [FJOI2016]神秘数 (主席树)
好久没打主席树了,都忘了怎么用了...... 假设我们选了一些数能构成[0,x]范围内的所有值,下一个要加的数是k(k<=x+1),那么可以取到[0,x+k]内的所有取值,所以有一种做法: 对于 ...
- (bzoj4408)[FJOI2016]神秘数(可持久化线段树)
(bzoj4408)[FJOI2016]神秘数(可持久化线段树) bzoj luogu 对于一个区间的数,排序之后从左到右每一个数扫 如果扫到某个数a时已经证明了前面的数能表示[1,x],那么分情况: ...
- 【BZOJ4408】[FJOI2016]神秘数(主席树)
[BZOJ4408][FJOI2016]神秘数(主席树) 题面 BZOJ 洛谷 题解 考虑只有一次询问. 我们把所有数排个序,假设当前可以表示出的最大数是\(x\). 起始\(x=0\). 依次考虑接 ...
- 【LG4587】[FJOI2016]神秘数
[LG4587][FJOI2016]神秘数 题面 洛谷 题解 首先我们想一想暴力怎么做 对于一段区间\([l,r]\) 我们先将它之间的数升序排序 从左往右扫, 设当前我们可以表示出的数为\([1,x ...
- BZOJ4299 & CC FRBSUM:ForbiddenSum & BZOJ4408 & 洛谷4587 & LOJ2174:[FJOI2016]神秘数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4299 https://www.lydsy.com/JudgeOnline/problem.php? ...
随机推荐
- Android之移动热修复
阿里云推出了移动热修复服务,听说这个服务傻瓜式接入,性能相对较好,对新技术比较好奇的我决定尝试一下. 1.首先,需要开通这个服务,创建应用 2.然后,在项目中接入服务.按照文档所述 第一步:gradl ...
- 使用VSTS的Git进行版本控制(六)——拉取请求
使用VSTS的Git进行版本控制(六)--拉取请求 在将代码合并到主干之前,拉取请求让团队对特性分支的更改提供反馈.审阅人可以通过建议修改留下评论,并投票批准或拒绝代码. 任务1:在Visual St ...
- Maven 安装 on centos7
本文演示如何在CentOS7上安装maven. 1 准备工作 1.1 进入官网下载栏目 http://maven.apache.org/download.cgi 找到下载列表中 Binary tar. ...
- genymotion和adb的解决方法
问题: 安装了genymotion后.再单独安装了adb 然后在关闭genymotion后,输入adb devices,下方显示为空,然后打开genymotion,cmd输入adb devices,显 ...
- 06-OpenLDAP密码策略
阅读视图 openldap密码策略 OpenLDAP服务端定制密码策略 客户端策划策略实例 定义用户第一次登录就修改密码 问题排查手册 重点推荐官方文档 备注:本文依然承接系列文. 1. openld ...
- 洗礼灵魂,修炼python(22)--自定义函数(3)—函数作用域,闭包
前面你看到嵌套两层的函数,也许你有感而发,想来点刺激的对不?那么如果每层内的变量名如果相同会怎样?拿个例子看下就知道: 报错了,报错信息大意是,本地变量‘num’引用前没有被赋值定义.这咋回事,我外层 ...
- SQL Server 2005详细安装过程及配置
说明:个人感觉SQL Server 2005是目前所有的SQL Server版本当中最好用的一个版本了,原因就是这个版本比起其它版本来说要安装简单,操作简便,只可惜这个版本只能在Windows7或者低 ...
- 解决windows 挂载 nfs 驱动器中 中文乱码问题
乱码问题,是由于 mount.nfs 命令不支持 utf-8字符集.所以是系统软件支持的问题.在网络上找了很多方案都没能解决. 网上主要有三种方案(1)换解决方案,使用smb 共享,这等于不是解决方法 ...
- [Mac] How do I move a window whose title bar is off-screen?
有时窗口一不小心拖出视野外了,此时无法移动窗口.如何还原? 有人遇到相似问题,已有解决方法: 方法就是,菜单 Windows - Zoom 这时窗口会还原.
- IO流(字节流,字符流,缓冲流)
一:IO流的分类(组织架构) 根据处理数据类型的不同分为:字节流和字符流 根据数据流向不同分为:输入流和输出流 这么庞大的体系里面,常用的就那么几个,我们把它们抽取出来,如下图: 二:字符字节 ...