• loj#6279. 数列分块入门 3


    #6279. 数列分块入门 3

    题目:传送门 

    简要题意:

       给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,询问区间内小于某个值 x 的前驱(比其小的最大元素)。


    题解:

       有点无耻的用一波set,其实就和分块2差不多嘛,找一下大于等于该元素的数,位置减一就ok


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<set>
     8 using namespace std;
     9 int n,a[110000],ba[110000];
    10 int block,pos[110000];
    11 set<int> s[110];
    12 void update(int l,int r,int c)
    13 {
    14     for(int i=l;i<=min(pos[l]*block,r);i++)
    15     {
    16         s[pos[i]].erase(a[i]);
    17         a[i]+=c;
    18         s[pos[i]].insert(a[i]);
    19     }
    20     if(pos[l]!=pos[r])
    21         for(int i=(pos[r]-1)*block+1;i<=r;i++)
    22         {
    23             s[pos[i]].erase(a[i]);
    24             a[i]+=c;
    25             s[pos[i]].insert(a[i]);
    26         }
    27     for(int i=pos[l]+1;i<=pos[r]-1;i++)ba[i]+=c;
    28 }
    29 void sol(int l,int r,int c)
    30 {
    31     int ans=-1;
    32     for(int i=l;i<=min(pos[l]*block,r);i++)if(a[i]+ba[pos[i]]<c)ans=max(ans,a[i]+ba[pos[i]]);
    33     if(pos[l]!=pos[r])
    34         for(int i=(pos[r]-1)*block+1;i<=r;i++)
    35             if(a[i]+ba[pos[i]]<c)
    36                 ans=max(ans,a[i]+ba[pos[i]]);
    37     for(int i=pos[l]+1;i<=pos[r]-1;i++)
    38     {
    39         int x=c-ba[i];
    40         set<int>::iterator it=s[i].lower_bound(x);
    41         if(it==s[i].begin())continue;
    42         it--;
    43         ans=max(ans,*it+ba[i]);
    44     }
    45     printf("%d
    ",ans);
    46 }
    47 int main()
    48 {
    49     memset(pos,0,sizeof(pos));memset(ba,0,sizeof(ba));
    50     scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    51     block=1000;for(int i=1;i<=n;i++){pos[i]=(i-1)/block+1;s[pos[i]].insert(a[i]);}
    52     for(int i=1;i<=n;i++)
    53     {
    54         int opt,l,r,c;
    55         scanf("%d%d%d%d",&opt,&l,&r,&c);
    56         if(opt==0)update(l,r,c);
    57         else sol(l,r,c);
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    家庭记账本APP开发准备(二)
    使用花生壳5做内网穿透
    课堂练习之可视化的强化版
    第五周总结
    课堂练习之疫情可视化
    第四周总结
    第三周总结
    第二周总结
    课堂练习之最大子数组
    软工第二学期开课博客
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8580579.html
Copyright © 2020-2023  润新知