正解:主席树
解题报告:
先放下传送门QAQ
首先可以先思考如果只有一组询问,怎么解决
可以这么想,最开始一个数也麻油的时候能表示的最大的数是0嘛
然后先排个序,按顺序每次新加入一个数x,设加入这个数之前能表示的最大的数是y
首先显然的是如果x>y+1,y+1一定不能被表示出来,就GG了
如果x<=y+1,那么能表示出来的最大的数就一定是x+y,就更新一下y+=x
从上面这个式子我们可以得到实际上每加入一个数,当可以继续下去的时候其实就是y=∑x
然后现在考虑是有多组询问的鸭怎么搞呢QAQ?
可以考虑这样子:对于当前的x,查询<=x的数的和
那显然就是线段树,存[l,r]的和,非常基础的套路辣
然后因为是问的区间内,所以用个主席树就好
然后就麻油啦啦啦!
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ll long long
#define gc getchar()
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];~i;i=edge[i].nxt)
const int N=100000+10,inf=1e9,M=1e8;
int n,m,rt[N],nod_cnt;
bool gdgs=1;
struct chtr{int ls,rs,dat;}tr[M];
il int read()
{
rc ch=gc;ri x=0;rb y=1;
while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
if(ch=='-')ch=gc,y=0;
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
return y?x:-x;
}
il int modify(ri x,ri l,ri r,ri dat)
{
ri nw=++nod_cnt;
tr[nw]=tr[x];tr[nw].dat+=dat;if(l==r)return nw;
if(dat<=((l+r)>>1))tr[nw].ls=modify(tr[x].ls,l,(l+r)>>1,dat);else tr[nw].rs=modify(tr[x].rs,((l+r)>>1)+1,r,dat);return nw;
}
il int query(int x1,int x2,int l,int r,int dat)
{
if(l==r)return tr[x2].dat-tr[x1].dat;
if(dat<=((l+r)>>1))return query(tr[x1].ls,tr[x2].ls,l,(l+r)>>1,dat);return tr[tr[x2].ls].dat-tr[tr[x1].ls].dat+query(tr[x1].rs,tr[x2].rs,((l+r)>>1)+1,r,dat);
}
int main()
{
// freopen("4587.in","r",stdin);freopen("4587.out","w",stdout);
n=read();rp(i,1,n)rt[i]=modify(rt[i-1],1,inf,read());
m=read();while(m--){int l=read(),r=read(),as=0;while(gdgs){int tmp=query(rt[l-1],rt[r],1,inf,as+1);if(tmp==as)break;as=tmp;}printf("%d\n",as+1);}
return 0;
}