4408: [Fjoi 2016]神秘数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 475  Solved: 287
[Submit][Status][Discuss]

Description

一个可重复数字集合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]所构成的可重复数字集合的神秘数。

Input

第一行一个整数n,表示数字个数。
第二行n个整数,从1编号。
第三行一个整数m,表示询问个数。
以下m行,每行一对整数l,r,表示一个询问。

Output

对于每个询问,输出一行对应的答案。

Sample Input

5
1 2 4 9 10
5
1 1
1 2
1 3
1 4
1 5

Sample Output

2
4
8
8
8

HINT

对于100%的数据点,n,m <= 100000,∑a[i] <= 10^9

Source

鸣谢yyh上传

Solution

这题的思路还是很妙的。

我们假设前面选的数能取到的最大值为k,即[1,k]中的所有数都能取到,现在加入了一个数x。

若x <= k+1,则能取到的最大值为k+x,神秘数为k+x+1

若x > k+1,则能取到的最大值仍为k,神秘数为k+1

对于一个询问(l,r),设当前神秘数为k,若Σai >= k(ai <= k && i∈[l,r]),则说明k仍能增大,否则,神秘数即为k。

而求前缀和,可以用可持久化线段树来解决。

每次寻找,k至少增加一倍,每次求前缀和是logn,总的时间复杂度是O(Q*log1e92)

Code

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm> using namespace std; #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
typedef long long LL;
const int maxn = 1e5+;
int n, a[maxn];
struct Node
{
LL sum; int ls, rs;
Node() { sum = ls = rs = ; }
}t[maxn*];
int rt[maxn], t_cnt, mx_a; void pushup(Node &x) { x.sum = t[x.ls].sum+t[x.rs].sum; } void update(int now_rt, int las_rt, int l, int r, int x)
{
if (l == r)
{
t[now_rt].sum = t[las_rt].sum+x;
return ;
}
int mid = (l+r)>>;
if (x <= mid)
{
t[now_rt].rs = t[las_rt].rs, t[now_rt].ls = ++t_cnt;
update(t[now_rt].ls, t[las_rt].ls, l, mid, x);
}
else
{
t[now_rt].ls = t[las_rt].ls, t[now_rt].rs = ++t_cnt;
update(t[now_rt].rs, t[las_rt].rs, mid+, r, x);
}
pushup(t[now_rt]);
} int query(int rt_1, int rt_2, int l, int r, int x)
{
if (l > x) return ;
if (r <= x) return t[rt_2].sum-t[rt_1].sum;
int mid = (l+r)>>;
int ret = query(t[rt_1].ls, t[rt_2].ls, l, mid, x);
if (x > mid) ret += query(t[rt_1].rs, t[rt_2].rs, mid+, r, x);
return ret;
} int calc(int l, int r)
{
int ret = , temp = ;
while ((temp = query(rt[l-], rt[r], , mx_a, ret)) >= ret) ret = temp+;
return ret;
} int main()
{
scanf("%d", &n);
REP(i, , n) scanf("%d", &a[i]), mx_a = max(mx_a, a[i]);
REP(i, , n) update(rt[i] = ++t_cnt, rt[i-], , mx_a, a[i]);
int Q, l, r;
scanf("%d", &Q);
while (Q --)
{
scanf("%d %d", &l, &r);
printf("%d\n", calc(l, r));
}
return ;
}

【Codechef FRBSUM】【FJOI2016】【BZOJ4299】【BZOJ 4408】 可持久化线段树的更多相关文章

  1. bzoj 3123 可持久化线段树启发式合并

    首先没有连边的操作的时候,我们可以用可持久化线段树来维护这棵树的信息,建立权值可持久化线段树,那么每个点继承父节点的线段树,当询问为x,y的时候我们可以询问rot[x]+rot[y]-rot[lca( ...

  2. bzoj 3207 可持久化线段树

    首先因为固定询问长度,所以我们可以将整个长度为n的数列hash成长度为n-k+1的数列,每次询问的序列也hash成一个数,然后询问这个数是不是在某个区间中出现过,这样我们可以根据初始数列的权值建立可持 ...

  3. bzoj 3524 可持久化线段树

    我们可以先离散化,然后建立权值的可持久化线段树,记录每个数出现的次数,对于区间询问直接判断左右儿子的cnt是不是大于(r-k+1)/2,然后递归到最后一层要是还是大于就有,否则不存在. 反思:挺简单一 ...

  4. bzoj 3207 可持久化线段树+hash

    这道题要看出来这个做法还是比较容易说一下细节 1.因为要用hash的区间值域来建树,而hash为了不冲突要开的很大,所以值域就会比较的大,不过这道题好的一点是没有修改,所以直接离散一下就会小很多 2. ...

  5. BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 9280  Solved: 2421 ...

  6. Bzoj 4408: [Fjoi 2016]神秘数 可持久化线段树,神题

    4408: [Fjoi 2016]神秘数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 177  Solved: 128[Submit][Status ...

  7. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  8. BZOJ 4408: [Fjoi 2016]神秘数 可持久化线段树

    4408: [Fjoi 2016]神秘数 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4408 Description 一个可重复数字集 ...

  9. (bzoj4408)[FJOI2016]神秘数(可持久化线段树)

    (bzoj4408)[FJOI2016]神秘数(可持久化线段树) bzoj luogu 对于一个区间的数,排序之后从左到右每一个数扫 如果扫到某个数a时已经证明了前面的数能表示[1,x],那么分情况: ...

随机推荐

  1. '增量赋值(augmented assignment)', 多么痛的领悟!

    '增量赋值(augmented assignment)', 多么痛的领悟! 深刻理解x += a 与 x = x + a 的不同: 按理说上面的两条语句是等价的, 功能上完全一样的. 之所以说不同, ...

  2. jQuery中Animate进阶用法(二)

    Step Type: Function( Number now, Tween tween )每个动画元素的每个动画属性将调用的函数.这个函数为修改Tween 对象提供了一个机会来改变设置中得属性值. ...

  3. javascript私有方法揭示为公有方法

    揭示模式可用于将私有方法暴露为公共方法.当为了对象的运转而将所有功能放置在一个对象中以及想尽可能地保护该对象,这种揭示模式就非常有用. 板栗: var myarray; (function(){ va ...

  4. 20155233 2016-2017-2 《Java程序设计》第5周学习总结

    20155233 2016-2017-2 <Java程序设计>第5周学习总结 学习目标 理解异常架构 牚握try...catch...finally处理异常的方法 会用throw,thro ...

  5. DataTable转Json(兼容easyUI特殊json分页)

    用法:上述方法是DataTable的扩展方法:静态类静态方法,变量前用this (一)ps:普通datatable转标准json DataTable dt = 获取db中的datatable数据. s ...

  6. H2内嵌数据库使用步骤

    1.找到h2数据库的jar包 D:\repositories\com\h2database\h2\1.4.187\h2-1.4.187.jar 2.双击jar包,配置连接信息 Driver Class ...

  7. jquery easyui:tab自动加载第一个tab内容

    $('#resourceTabs').tabs('unselect', 0);$('#resourceTabs').tabs('select', 0);

  8. django和flask关于oralce数据库配置

    Django中关于Oracle数据库配置 # 使用SERVICE_NAME DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracl ...

  9. ScheduledThreadExecutor定时任务线程池

    ScheduledThreadPoolExecutor 继承自ThreadPoolExecutor实现了ScheduledExecutorService接口.主要完成定时或者周期的执行线程任务. 代码 ...

  10. 开启@EnableRedisHttpSession

    sessionId=569662ce-c6d5-42a9-a94b-c9df826df716 1800秒后失效 sessionId=23913542-9b5f-4699-8a87-1023b57f5f ...