正解:主席树
解题报告:
先放下传送门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=+,inf=1e9,M=1e8;
int n,m,rt[N],nod_cnt;
bool gdgs=;
struct chtr{int ls,rs,dat;}tr[M]; il int read()
{
rc ch=gc;ri x=;rb y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),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)>>))tr[nw].ls=modify(tr[x].ls,l,(l+r)>>,dat);else tr[nw].rs=modify(tr[x].rs,((l+r)>>)+,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)>>))return query(tr[x1].ls,tr[x2].ls,l,(l+r)>>,dat);return tr[tr[x2].ls].dat-tr[tr[x1].ls].dat+query(tr[x1].rs,tr[x2].rs,((l+r)>>)+,r,dat);
} int main()
{
// freopen("4587.in","r",stdin);freopen("4587.out","w",stdout);
n=read();rp(i,,n)rt[i]=modify(rt[i-],,inf,read());
m=read();while(m--){int l=read(),r=read(),as=;while(gdgs){int tmp=query(rt[l-],rt[r],,inf,as+);if(tmp==as)break;as=tmp;}printf("%d\n",as+);}
return ;
}
这儿是代码QwQ!