#6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))
Posted Let_Life_Stop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))相关的知识,希望对你有一定的参考价值。
题目链接:https://loj.ac/problem/6279
题目大意:中文题目
具体思路:按照上一个题的模板改就行了,但是注意在整块查找的时候的下标问题。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 const int maxn = 2e5+100; 5 const int mod = 1e8+7; 6 const int inf = 0x3f3f3f3f; 7 ll l[maxn],r[maxn],belong[maxn]; 8 ll add[maxn],a[maxn],b[maxn]; 9 int n; 10 void buildblock() 11 { 12 ll tmp=(ll)sqrt(n); 13 ll tot=n/tmp; 14 if(n%tmp) 15 tot++; 16 for(ll i=1; i<=n; i++) 17 { 18 belong[i]=(i-1)/tmp+1ll; 19 } 20 for(ll i=1; i<=tot; i++) 21 { 22 l[i]=(i-1)*tmp+1ll; 23 r[i]=i*tmp; 24 } 25 r[tot]=n; 26 for(ll i=1; i<=tot; i++) 27 { 28 sort(b+l[i],b+r[i]+1); 29 } 30 } 31 void init(int tmp){ 32 for(int i=l[tmp];i<=r[tmp];i++)b[i]=a[i]; 33 sort(b+l[tmp],b+r[tmp]+1); 34 } 35 void update(ll st,ll ed,ll val) 36 { 37 if(belong[st]==belong[ed]) 38 { 39 for(ll i=st; i<=ed; i++)a[i]+=val; 40 init(belong[st]); 41 return ; 42 } 43 for(ll i=st; i<=r[belong[st]]; i++)a[i]+=val; 44 init(belong[st]); 45 for(ll i=l[belong[ed]]; i<=ed; i++)a[i]+=val; 46 init(belong[ed]); 47 for(ll i=belong[st]+1; i<belong[ed]; i++) 48 add[i]+=val; 49 } 50 ll ask(ll st,ll ed,ll val) 51 { 52 ll ans=-inf; 53 if(belong[st]==belong[ed]) 54 { 55 for(ll i=st; i<=ed; i++) 56 { 57 if(a[i]+add[belong[st]]>=val)continue; 58 ans=max(ans,a[i]+add[belong[st]]); 59 } 60 return ans; 61 } 62 for(ll i=st; i<=r[belong[st]]; i++) 63 { 64 if(a[i]+add[belong[st]]>=val)continue; 65 ans=max(ans,a[i]+add[belong[st]]); 66 } 67 for(ll i=l[belong[ed]]; i<=ed; i++) 68 { 69 if(a[i]+add[belong[ed]]>=val)continue; 70 ans=max(ans,a[i]+add[belong[ed]]); 71 } 72 for(ll i=belong[st]+1; i<belong[ed]; i++) 73 { 74 ll tmp=val-add[i]; 75 ll id=lower_bound(b+l[i],b+r[i]+1,tmp)-(b+l[i]); 76 if(id==0)continue; 77 ans=max(ans,b[l[i]+id-1]+add[i]); 78 } 79 return ans; 80 } 81 int main() 82 { 83 // freopen("hqx.in","r",stdin); 84 // cout<<lower_bound(a,a+5,2)-a<<endl; 85 scanf("%d",&n); 86 for(int i=1; i<=n; i++) 87 { 88 scanf("%lld",&a[i]); 89 b[i]=a[i]; 90 } 91 buildblock(); 92 ll op,st,ed; 93 ll val; 94 while(n--) 95 { 96 scanf("%lld %lld %lld %lld",&op,&st,&ed,&val); 97 if(op==0) 98 { 99 update(st,ed,val); 100 } 101 else if(op==1) 102 { 103 ll tmp=ask(st,ed,val); 104 printf("%lld\n",tmp==-inf?-1:tmp); 105 } 106 } 107 return 0; 108 }
以上是关于#6279. 数列分块入门 3(询问区间内小于某个值 xx 的前驱(比其小的最大元素))的主要内容,如果未能解决你的问题,请参考以下文章