#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 的前驱(比其小的最大元素))的主要内容,如果未能解决你的问题,请参考以下文章

LOJ#6279. 数列分块入门 3

Loj 6279. 数列分块入门 3

LibreOj 6279数列分块入门 3 练习了一下set

LibreOJ 6278. 数列分块入门 2 题解

#6278. 数列分块入门 2

「分块」数列分块入门2 by hzwer