[FJOI2016]神秘数

Description:

给定一个数列,每次询问不能被区间\([L,R]\)所有数的任何子集表示的最小正整数

Hint:

\(n \le 10^5 ,a_i \le 10^9\)

Solution:

很好的思维题

我们先令\(Ans=1\),使区间中的数从小到大依次加入

考虑已知能表示的值域为\([1,x]\),现在的最小答案\(Ans=x+1\),重新考虑小于\(Ans\)的数对\(ans\)造成的影响

显然最多表示出\([1,\sum a_i(a_i<Ans)]\) (因为之前的为\([1,\sum a_i(a[i]<Ans_{pre})]\),加进来的数一定都能和之前的数表示出这一段)

如果\(\sum a_i(a_i<Ans)\) \(>= Ans\) 则 ans =\(\sum a_i(a_i<Ans)+1\)

否则直接输出答案

所以可以用主席树维护,复杂度\(O(mlogn* loga_i)\)

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mxn=1e5+5,inf=1e9;
ll n,m,cnt,tot,hd[mxn],a[mxn];
ll rt[mxn<<5],ls[mxn<<5],rs[mxn<<5];
ll sum[mxn<<5];

inline ll read() {
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

struct ed {
	ll to,nxt;
}t[mxn<<1];

inline void add(ll u,ll v) {
	t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
}

void update(ll las,ll &p,ll l,ll r,ll pos,ll val) {
	if(!p) p=++tot; sum[p]=sum[las]+val;
	if(l==r) return ; ll mid=(l+r)>>1;
	if(pos<=mid) update(ls[las],ls[p],l,mid,pos,val),rs[p]=rs[las];
	else update(rs[las],rs[p],mid+1,r,pos,val),ls[p]=ls[las];
}

ll query(ll las,ll p,ll l,ll r,ll pos) {
	if(l==r) return sum[p]-sum[las]; ll mid=(l+r)>>1; 
	if(pos<=mid) return query(ls[las],ls[p],l,mid,pos);
	else return sum[ls[p]]-sum[ls[las]]+query(rs[las],rs[p],mid+1,r,pos);
}

int main()
{
	n=read(); ll l,r;
	for(ll i=1;i<=n;++i) 
		a[i]=read(),update(rt[i-1],rt[i],1,inf,a[i],a[i]);
	m=read(); sort(a+1,a+n+1); 
	for(ll i=1;i<=m;++i) {
		l=read(),r=read();
		ll ans=1;
		while(1) {
			ll pos=upper_bound(a+1,a+n+1,ans)-a-1; ll x;
			if((x=query(rt[l-1],rt[r],1,inf,ans))>=ans) ans=x+1;
			else break ;
		}
		printf("%lld\n",ans);
	}
    return 0;
}

posted @ 2019-03-26 11:29  cloud_9  阅读(217)  评论(0编辑  收藏  举报