[ABC388G] Simultaneous Kagamimochi 2
题目大意
详细题目传送门
给出 \(n\) 和长度为 \(n\) 的单调不降序列 \(a\)。
多组询问对于每一个 \(l,r\),求出最多可以分出多少对 \(a_i,a_j\) 满足 \(2\cdot a_i\leq a_j\),每一个 \(a_i,a_j\) 不能重复使用。询问互相独立。
\(n,Q\leq2\cdot 10^5\)
思路
先考虑单组询问情况,即 E 题。发现二分出一个最大的 \(k\) 满足 \(\forall 2\cdot a_i\leq a_{r-k+i},i\in [l,l+k-1]\)。
发现对于多组数据的情况瓶颈在于判断 \(k\) 是否可行的 \(O(n)\) 时间复杂度。发现这些 \(a_i\) 的对应点是具有单调性的,所以我们 \(O(n)\) 找到对于每一个 \(a_i\) 的 \(\max(j)\) 满足 \(2\cdot a_j\leq a_i\)。设 \(b_i=i-\max(j)\)。则上式就可以转化成 \(l+\max(b_{r-k+1},\cdots,b_{r})\stackrel{?}{<}r-k\)。用 ST 表维护区间 \(b_i\) 最大值即可。
时间复杂度 \(O(n\log n +Q\log n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=2e5+5;
ll n,a[MAXN];
ll st[MAXN][20],lg[MAXN];
ll query(ll l,ll r){
ll g=lg[r-l+1];
return max(st[l][g],st[r-(1<<g)+1][g]);
}
bool check(ll l,ll r,ll k){
return l+query(r-k+1,r)<=r-k+1;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=2;i<=n+3;++i){
lg[i]=lg[i-1]+(i==(1<<(lg[i-1]+1)));
}
ll j=1;
for(int i=1;i<=n;++i){
cin>>a[i];
while(j<i&&a[j]*2<=a[i]){
++j;
}
st[i][0]=i-j+1;
}
for(int j=1;j<=lg[n];++j){
for(int i=1;i+(1<<j)-1<=n;++i){
st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
}
ll Q;
cin>>Q;
while(Q--){
ll l,r;
cin>>l>>r;
ll L=0,R=(r-l+1)/2,ans=0;
while(L<=R){
ll mid=(L+R)>>1;
if(check(l,r,mid)){
ans=mid;
L=mid+1;
}else{
R=mid-1;
}
}
cout<<ans<<endl;
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验