P4587 [FJOI2016]神秘数-题解

P4587 [FJOI2016]神秘数-题解#

思路

我们考虑将询问的区间 [l,r] 内的所有数先从小到大排序,然后从左到右扫一遍

我们假设当前扫到了 ai 且用 alai1 所能表示的值域为 [1,x]

  • ai>x+1,则我们无论如何都表示不出 x+1,直接输出答案

  • 否则 aix+1,则此时我们可以表示的值域就变为 [1,x+ai]

这样的朴素暴力时间复杂度是 O(nmlogn) 的,需要优化

若当前的答案为 ans,且小于等于 ans 的数的和为 res,则显然 ans 需要更新为 res+1

否则答案就是 ans

那我们所需要的就是维护某段区间内的某段值域内所有数的和

显然用主席树维护

时间复杂度为 O((n+m)lognlog(ai))

code

#include<bits/stdc++.h>
using namespace std;

#define doge_is_god 1
const int N=1e5+5;
const int inf=1e9;

inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

int n,m;
int a[N],rt[N];

namespace CT{
	struct node{
		int v,l,r;
	}t[N*31];
	int cnt;
	inline void insert(int &p,int pre,int l,int r,int x,int k){
		p=++cnt;
		t[p]=t[pre];
		t[p].v+=k;
		if(l==r) return;
		int mid=l+r>>1;
		if(x<=mid) insert(t[p].l,t[pre].l,l,mid,x,k);
		else insert(t[p].r,t[pre].r,mid+1,r,x,k);
	}
	inline int query(int q,int p,int l,int r,int L,int R){
		if(L<=l&&r<=R) return t[p].v-t[q].v;
		int mid=l+r>>1,res=0;
		if(L<=mid) res+=query(t[q].l,t[p].l,l,mid,L,R);
		if(mid<R) res+=query(t[q].r,t[p].r,mid+1,r,L,R);
		return res;
	}
}

signed main(){
	n=read();
	for(int i=1;i<=n;++i){
		a[i]=read();
		CT::insert(rt[i],rt[i-1],1,inf,a[i],a[i]);
	}
	m=read();
	while(m--){
		int l=read(),r=read(),ans=1;
		while(doge_is_god){
			int res=CT::query(rt[l-1],rt[r],1,inf,1,ans);
			if(res>=ans) ans=res+1;
			else break;
		}
		printf("%d\n",ans);
	}
}

作者:Into_qwq

出处:https://www.cnblogs.com/into-qwq/p/16530133.html

版权:本作品采用「qwq」许可协议进行许可。

posted @   Into_qwq  阅读(137)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示