题目大意:一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数,给出a[],多次询问 a[l],a[l+1]…,a[r] 的神秘数
题解:设当前神秘数为
ans
,新加入
x
1.
2.
x>ans
,
ans
不变
对于每个询问,从 ans=1 开始,求出 get=∑ai≤ansai ,更新答案
O(mlog21e9)
我的收获:强啊
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
#define INF 1e9
#define M 100005
#define MX M*100
#define lson tl[x],tl[y],l,mid
#define rson tr[x],tr[y],mid+1,r
int n,m,cnt,a[M],root[M];
int tl[MX],tr[MX],sum[MX];
inline void node(int &x,int w,int v){x=++cnt,sum[x]=sum[w]+v,tl[x]=tl[w],tr[x]=tr[w];}
void insert(int x,int &y,int l,int r,int k)
{
node(y,x,k);
if(l==r) return ;
int mid=(l+r)>>1;
if(k<=mid) insert(lson,k);
else insert(rson,k);
}
int query(int x,int y,int l,int r,int k)
{
if(l==r) return sum[y]-sum[x];
int mid=(l+r)>>1;
if(k<=mid) return query(lson,k);
return query(rson,k)+sum[tl[y]]-sum[tl[x]];
}
void work()
{
while(m--){
int l,r;scanf("%d%d",&l,&r);
int ans=1;
while(1){
int get=query(root[l-1],root[r],1,INF,ans);
if(get<ans) break;
ans=get+1;
}
printf("%d\n",ans);
}
}
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) insert(root[i-1],root[i],1,INF,a[i]);
scanf("%d",&m);
}
int main()
{
init();
work();
return 0;
}