【CodeChef】ForbiddenSum
Solution
场上想到了\(O(NM)\)的做法。。然而并没有什么用
首先考虑比较简单的一个问题,给定一个数组\(A\),问这些数不能凑成的最小的数是多少
有一个很简单的想法:显然\(0\)不管对于哪个数组来说都是可以表示的,所以接下来我们只用从\(1\)开始考虑,如果说我知道一个最大的\(x\),满足\([1,x]\)这个区间内的数都能被当前数组中的数表示出来,这个时候如果说新加入一个数\(a\),考虑\(x\)会有什么变化
会发现如果说\(a<=x+1\)的话,那么这个最大值会从\(x\)变成\(x+a\),构造一下就知道了:对于\([1,x]\)中的整数显然都可以被表示出来,而\([x+1,x+a]\)这个区间中的每一个数\(i\)都可由\((i-a)\)和\(a\)组成,而\((i-a)\in [1,x]\),所以成立;当\(a>x+1\)的话,就没有办法连上了
这样得出了整个数组的\(x\)之后,\(x+1\)就是答案了
所以我们可以得到一个\(O(NM)\)的做法,就是每个询问区间暴力扫一遍
由于要排序,这个算法看起来好像非常难优化,但实际上我们如果换一种角度来看这个算法的流程就比较好优化了:绕开排序这个瓶颈,放在整个无序的数组上面进行操作,注意到上面提及的\(x\)其实是这个数组中某些元素的和,所以这个\(x\)其实应该是一个\(sum\),我们每次在做的事情就是找到一个新的\(<=sum+1\)的元素,并且将它加进\(sum\)里面去,直到找不到新的元素为止,由于\(sum\)本身是递增的,所以无形中相当于从小到大考虑每个元素
注意到这个寻找新元素的过程并没有必要一个一个元素地找,实际上我们会发现,对于当前\(sum\)来说那些\(<=sum+1\)的新元素一定会在后面的操作中被加进来(因为\(sum\)只会越来越大),所以每次我们可以将当前\(<=sum+1\)的所有新元素全部加进来就好了
于是问题就转变成了一个求区间中某个范围内的数的和的问题,直接主席树动态开点一波(注意根本不需要离散化之类的(实际上也不能离散化== )。。因为。。动态开点。。所以点数还是\(nlogn\)级别的==)
至于时间复杂度:首先每次主席树查找是\(logn\)的,然后。。至于一次询问会查找几次呢。。实际上我们会发现每次\(sum\)都至少会变成原来的\(2\)倍,然后题目又说了总和\(<=10^9\),那么就是最坏\(log_2(10^9)\)次左右,问题不大(然而这个\(2\)倍。。打表发现==其实是因为每次只要还有新的值,至少都会加上一个\(sum+1\))
代码大概张这个样子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10,SEG=N*20;
int a[N],tmp[N];
int n,m;
namespace Seg{/*{{{*/
int ch[SEG][2],sz[SEG],rt[N],sum[SEG];
int n,tot;
void init(int _n){tot=0; ch[0][0]=ch[0][1]=0; rt[0]=0; sz[0]=sum[0]=0; n=_n;}
int newnode(int pre){
ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; sz[tot]=sz[pre]; sum[tot]=sum[pre];
return tot;
}
void pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]];sum[x]=sum[ch[x][0]]+sum[ch[x][1]];}
void _insert(int pre,int &x,int d,int lx,int rx){
x=newnode(pre);
if (lx==rx){++sz[x];sum[x]+=lx;return;}
int mid=lx+rx>>1;
if (d<=mid) _insert(ch[pre][0],ch[x][0],d,lx,mid);
else _insert(ch[pre][1],ch[x][1],d,mid+1,rx);
pushup(x);
}
void insert(int pre,int x,int d){_insert(rt[pre],rt[x],d,1,n);}
int _query(int L,int R,int l,int r,int lx,int rx){
if (!L&&!R) return 0;
if (l<=lx&&rx<=r) return sum[R]-sum[L];
int mid=lx+rx>>1,ret=0;
if (l<=mid) ret+=_query(ch[L][0],ch[R][0],l,r,lx,mid);
if (r>mid) ret+=_query(ch[L][1],ch[R][1],l,r,mid+1,rx);
return ret;
}
int query(int L,int R,int l,int r){return _query(rt[L-1],rt[R],l,r,1,n);}
}/*}}}*/
void solve(int l,int r){
int sum=0,tmp,pre=0;
while (1){
tmp=Seg::query(l,r,1,sum+1);
if (tmp==pre){
printf("%d\n",sum+1);
return;
}
sum=tmp; pre=tmp;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int l,r,mx=0;
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d",a+i);
mx=max(mx,a[i]);
}
Seg::init(mx);
for (int i=1;i<=n;++i)
Seg::insert(i-1,i,a[i]);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%d%d",&l,&r);
solve(l,r);
}
}
【CodeChef】ForbiddenSum的更多相关文章
- 【CodeChef】Querying on a Grid(分治,最短路)
[CodeChef]Querying on a Grid(分治,最短路) 题面 Vjudge CodeChef 题解 考虑分治处理这个问题,每次取一个\(mid\),对于\(mid\)上的三个点构建最 ...
- 【CodeChef】Palindromeness(回文树)
[CodeChef]Palindromeness(回文树) 题面 Vjudge CodeChef 中文版题面 题解 构建回文树,现在的问题就是要求出当前回文串节点的长度的一半的那个回文串所代表的节点 ...
- 【CodeChef】Find a special connected block - CONNECT(斯坦纳树)
[CodeChef]Find a special connected block - CONNECT(斯坦纳树) 题面 Vjudge 题解 还是一样的套路题,把每个数字映射到\([0,K)\)的整数, ...
- 【CODECHEF】【phollard rho + miller_rabin】The First Cube
All submissions for this problem are available. Read problems statements in Mandarin Chinese and Rus ...
- 【codechef】FN/Fibonacci Number
题意 给出 c 和 P ,求最小的非负整数 n 使得 \(Fib(n)=c(mod~ P)\) 其中 P 是质数且 模 10 等于一个完全平方数(也就是说 P 的末位是个完全平方数,那么只能是 1 或 ...
- 【CodeChef】Prime Distance On Tree
vjudge 给定一棵边长都是\(1\)的树,求有多少条路径长度为质数 树上路径自然是点分治去搞,但是发现要求是长度为质数,总不能对每一个质数都判断一遍吧 自然是不行的,这个东西显然是一个卷积,我们合 ...
- 【Codechef】Chef and Bike(二维多项式插值)
something wrong with my new blog! I can't type matrixs so I come back. qwq 题目:https://www.codechef.c ...
- 【Codechef】BB-Billboards
题解 传说中的--半标准杨表(行单调不增,列单调减) 如果N能整除M,我们把序列分成\(\frac{N}{M}\)段 然后里面要填K个1,显然我每一段必须填K个1,且可以构造出合法的序列,所以最少要填 ...
- 【CodeChef】QTREE- Queries on tree again!
题解 给你一棵基环树,环长为奇数(两点间最短路径只有一条) 维护两点间路径最大子段和,支持把一条路径上的值取反 显然只要断开一条边维护树上的值,然后对于那条边分类讨论就好了 维护树上的值可以通过树链剖 ...
随机推荐
- JAVA验证码识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本
JAVA验证识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本 工具准备: jTessBoxEditorFX下载:https://github.com/nguyenq/jT ...
- Zabbix自动发现之fping
原文发表于cu:2016-06-21 Zabbix自动发现功能从配置流程上比较简单:Discovery与Action. 在做Zabbix的自动发现验证时,使用"ICMP ping" ...
- centos上搭建git服务--3
前言:当我们想要实现几个小伙伴合作开发同一个项目,或者建立一个资源分享平台的时候,GIT就是一个很好的选择.当然,既然是一个共有平台,那么把这个平台放到个人计算机上明显是不合适的,因此就要在服务器上搭 ...
- Alpha阶段贡献分分配
作业要求[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2281] 要求1 每位组员的贡献分值 徐常实:14 张帅:13 王硕:12 赵佳 ...
- 冲刺ing-7
第七次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 Leangoo的看板截图,燃尽图 蔺皓雯 编写博客 蔡晨旸 进行测试 曾茜 界面设计 鲁婧楠 界面前后端 杨池宇 界面前后端 项目的发布说 ...
- mininet实验 连接floodlight控制器
参考博客一 参考博客二 事先准备-floodlight安装 Java安装方法及环境变量配置 执行ifconfig命令获取floodlight所在服务器的IP地址. 1.启动floodlight jav ...
- whu Problem 1537 - A - Stones I 贪心
题目链接: http://acm.whu.edu.cn/land/problem/detail?problem_id=1537 Stones I Time Limit: 1000MSMemory Li ...
- 人生的第一篇blog
开始写博客了,人生第一篇博客啊,要写些什么呢?想想也没有什么头绪,随便写写吧. 这学期要使用代码管理工具了,要写团队项目了.一直以来都是自己一个人在默默编程,没有过合作经历.对于代码的管理也只是一直在 ...
- CodeForces Round #527 (Div3) C. Prefixes and Suffixes
http://codeforces.com/contest/1092/problem/C Ivan wants to play a game with you. He picked some stri ...
- maven 实践 :管理依赖
有人认为Maven是一个依赖管理工具,当然这种想法是错误的(确切的说Maven是一个项目管理工具,贯穿了整个项目生命周期,编译,测试,打包,发布...),但Maven给人造成这种错误的印象也是有原因的 ...