题解【bzoj4587 & bzoj4408 [FJOI2016]神秘数】
Description
\(n\) 个数的序列,每次询问一个区间,求最小的一个数使得不能用这个区间中的数之和表示。
\(n \leq 10^5, \sum a_i \leq 10^9\)
这两个题一个是权限一个没有真是很方所以我在洛谷交
Solution
第一次用数组写数据结构真短啊
考虑只有一次询问怎么做
把给定的区间内的数排序,从小到大扫一遍。
如果一个数比他之前的数之和至少大了 \(1\) ,那么答案就是和 + 1
否则就可以把\([1,\text{前缀和}]\) 都表示出来(感性理解很容易)
这道题怎么做也就显然了起来。只需要用主席树维护区间中小于等于某个数的数之和即可。流程如下
当前答案是 \(a\),令 \(S\) 是区间中 \(\leq a\) 的数之和
- 如果 \(S < a\) 则 \(a\) 就是最后的答案
- 否则 让 \(a = S+1\) 然后重复此操作
最开始的时候 \(a=1\)
这样做的话 \(a\) 每次都会翻一倍,所以最后的总复杂度是 \(O(m \log n \log \sum a_i)\)
Code
我写的是动态开点的线段树维护的主席树
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 50000500;
const int L = 1000000000;
int n, m, a[N], cnt;
int root[N], ch[N][2]; ll sum[N];
inline void I (int pre, int now, int l, int r, int val) {
  ch[now][0] = ch[pre][0], ch[now][1] = ch[pre][1];
  int mid = (l + r) >> 1; sum[now] = sum[pre] + val; if(l == r) return ;
  if(val <= mid) ch[now][0] = ++cnt, I(ch[pre][0], ch[now][0], l, mid, val);
  else ch[now][1] = ++cnt, I(ch[pre][1], ch[now][1], mid + 1, r, val);
}
inline int Q(int pre, int now, int l, int r, int val) {
  if(l == r) return sum[now] - sum[pre]; int mid = (l + r) / 2;
  if(val <= mid) return Q(ch[pre][0], ch[now][0], l, mid, val);
  else return sum[ch[now][0]] - sum[ch[pre][0]] + Q(ch[pre][1], ch[now][1], mid + 1, r, val);
}
int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i++) {
    scanf("%d", &a[i]); root[i] = ++cnt;
    I(root[i - 1], root[i], 1, L, a[i]);
  } scanf("%d", &m);
  for(int i = 1; i <= m; i++) {
    int l, r; scanf("%d %d", &l, &r);
    int ans = 1;
    int S; while(1) {
      S = Q(root[l - 1], root[r], 1, L, ans);
      if(S < ans) { printf("%d\n", ans); break ; }
      else ans = S + 1;
    }
  }
  return 0;
}
题解【bzoj4587 & bzoj4408 [FJOI2016]神秘数】的更多相关文章
- (bzoj4408)[FJOI2016]神秘数(可持久化线段树)
		(bzoj4408)[FJOI2016]神秘数(可持久化线段树) bzoj luogu 对于一个区间的数,排序之后从左到右每一个数扫 如果扫到某个数a时已经证明了前面的数能表示[1,x],那么分情况: ... 
- [bzoj4408][Fjoi2016]神秘数
		Description 一个可重复数字集合$S$的神秘数定义为最小的不能被$S$的子集的和表示的正整数. 例如$S={1,1,1,4,13}$, $1=1$, $2=1+1$, $3=1+1+1$, ... 
- 【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? ... 
- [FJOI2016]神秘数(脑洞+可持久化)
		题目描述 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = 4+1 6 = ... 
- Luogu  P4587 [FJOI2016]神秘数
		一道好冷门的好题啊,算是对于一个小结论和数据结构的一点考验吧 首先看完题目我们发现要从这个神秘数的性质入手,我们观察or手玩可得: 如果有\(x\)个\(1\),那么\([1,x]\)都是可以表示出来 ... 
- 【BZOJ-4408】神秘数     可持久化线段树
		4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 475 Solved: 287[Submit][Status ... 
- BZOJ 4408 FJOI2016 神秘数 可持久化线段树
		Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1+13 = 1+1+14 = 45 = 4+16 ... 
随机推荐
- 爬虫_处理js动态加载
			1.selenium模块下载网页提取url,[煎蛋网] https://www.cnblogs.com/fat39/p/9865949.html#tag5 2.该网页加密了url,通过js获取图片.分 ... 
- 20135332 第一次JAVA实验报告
			课程:Java程序设计 班级: 1353 姓名:武西垚 学号:20135332 成绩: 指导教师:娄嘉鹏 实验日期:2 ... 
- Shell脚本 数据清洗
			需要做的任务是将上图类似的格式的文件进行处理,将年月日小时分别提取出来放到每行的行尾(上图已清洗好) 自己的思路是先用cut命令将每行的年月日小时提取出来,分别给一个变量,然后再循环利用sed命令将年 ... 
- 第二次作业利用java语言编写计算器进行四则运算
			随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ... 
- 假如 GFW 遇上 ML
			我稍微试了一下梯子 我稍微试了一下梯子,在有梯子的情况下进行google搜索,然后wireshark 抓包.所有问题跃然纸上 当前我认为:> 只要你和一个非国内的服务器长时高频交换数据,基本上就 ... 
- 乱码之UTF-8 &GBK
			在提交JSP时对于乱码问题,首先我们要搞清楚为什么会出现乱码? 看JSP的头文件:<%@ page contentType="text/html;charset=UTF-8" ... 
- golang数据类型转换
			int--string //string到int value_int,err:=strconv.Atoi(string) //int到string str:=strconv.Itoa(value_in ... 
- P4安装
			P4安装篇 ubuntu 14.04为例子 一.首先要fork到自己的github里面 源码目录 https://github.com/p4lang/p4factory 然后fork到自己的githu ... 
- typedef struct bit0 : 1
			这句话定义了一个位域,bit0是该位域的域名,而且bit0只占用一个位.位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.为了节省存储空间,并使处理简便,C语言提供了一种 ... 
- Spring 计划 7.0
			Sprint回顾 让我们一次比一次做得更好. 1.回顾组织 主题:“我们怎样才能在下个sprint中做的更好?” 时间:设定为1小时. 参与者:整个团队. 场所:宿舍. 秘书:李新佳. 2. ... 
