博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bzoj4299 Codechef FRBSUM
阅读量:7090 次
发布时间:2019-06-28

本文共 2555 字,大约阅读时间需要 8 分钟。

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 416  Solved: 276

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 5

Sample Output

2
4
8
8
8

HINT

 

对于100%的数据,1≤N,M≤100000,1≤A_i≤10^9,1≤A_1+A_2+…+A_N≤10^9。

 

 

Source

 

线段树 主席树 脑洞题

 

又是很神奇的结论题?

给定一个数列,假如我们现在可以用数列中的数凑出$[1,x]$范围内的所有数,若是能从数列中再找到一个$[1,x+1]$范围内的数,我们就可以凑出$[1,x+1]$范围的所有数。而如果我们只能再找到大于x+1的数,那么就无法继续凑了,最终答案是x+1 。

按照这个思想,我们可以提取出询问区间内的数,从小到大尝试答案:

  设当前可以凑出$[1,res]$范围。统计所有小于等于res+1的数的和sum,若$ sum>=res+1 $,说明我们可以凑出[1,sum]范围的数。

  令res=sum,继续尝试扩大范围。

我们发现如果每次区间都能扩大,至少会扩大为原来的两倍,可以在$O(log(n))$的时间内回答一个询问。

具体的查询可以用主席树维护。

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #define LL long long 7 using namespace std; 8 const int INF=1e9; 9 const int mxn=100010;10 int read(){11 int x=0,f=1;char ch=getchar();12 while(ch<'0' || ch>'9'){
if(ch=='-')f=-1;ch=getchar();}13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}14 return x*f;15 }16 struct node{17 int l,r;int smm;18 }t[mxn*60];19 int rot[mxn],cnt=0;20 #define lc t[rt].l21 #define rc t[rt].r22 void update(int p,int v,int l,int r,int y,int &rt){23 rt=++cnt;24 t[rt]=t[y];25 t[rt].smm+=v;26 if(l==r)return;27 int mid=(l+r)>>1;28 if(p<=mid)update(p,v,l,mid,t[y].l,lc);29 else update(p,v,mid+1,r,t[y].r,rc);30 return;31 }32 int query(int R,int l,int r,int y,int rt){33 if(r<=R){
return t[rt].smm-t[y].smm;}34 int mid=(l+r)>>1;35 if(R<=mid)return query(R,l,mid,t[y].l,lc);36 return query(R,l,mid,t[y].l,lc)+query(R,mid+1,r,t[y].r,rc);37 }38 int n,m;39 int a[mxn];40 int main(){41 int i,j;42 n=read();43 for(i=1;i<=n;i++)a[i]=read();44 for(i=1;i<=n;i++)update(a[i],a[i],1,1e9,rot[i-1],rot[i]);45 m=read();46 int L,R,ans=1;47 while(m--){48 L=read();R=read();int res=1;49 ans=min(INF,query(res,1,1e9,rot[L-1],rot[R]));50 while(ans>=res && res<1e9){51 res=ans+1;52 ans=min(INF,query(res,1,1e9,rot[L-1],rot[R]));53 }54 printf("%d\n",ans+1);55 }56 return 0;57 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/7011449.html

你可能感兴趣的文章
Oracle自动存储管理 ASMLib的支持变化
查看>>
hdu5079
查看>>
HttpUrlConnection的setDoOutput与setDoInput的区别
查看>>
Knockoutjs自学记录(一)~本地新建展示实例
查看>>
常量和数据类型
查看>>
javascript DOM操作
查看>>
Ajax
查看>>
mysql使用小结
查看>>
测试lua的效率
查看>>
vuex相关(actions和mutation的异曲同工)
查看>>
解决Maven项目相互依赖/循环依赖/双向依赖的问题
查看>>
UML
查看>>
HTTP 返回码中 301 与 302 的区别
查看>>
App自动化测试探索(二)MAC环境搭建iOS+Python+Appium测试环境
查看>>
使用MATPLOTLIB 制图(散点图,热力图)
查看>>
《深入PHP:面向对象、模式与实践》(一)
查看>>
[06] JavaScript 类型
查看>>
求最大值及其下标
查看>>
关于类型“LinkButton”的控件“xxx”必须放在具有 runat=server 的窗体标记内问题的解决方案...
查看>>
Javascript:DOM表格操作
查看>>