LibreOj6279 数列分块入门 3 区间加法+区间内找前驱

    xiaoxiao2023-10-17  157

    数列分块入门 3

    链接:LibreOj6279

    题目描述

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

    输入格式

    第一行输入一个数字n。

    第二行输入n个数字,第i个数字为a[i],以空格隔开。

    接下来输入n行询问,每行输入四个数字 op、l、r、c,以空格隔开。

    若 op==0,表示将位于[l,r] 的之间的数字都加 c。

    若 op==1,表示询问 [l,r]中,c的前驱(不存在的话输出-1)

    输出格式

    对于每次询问,输出一行一个数字表示答案。

    样例输入

    4 1 2 2 3 0 1 3 1 1 1 4 4 0 1 2 2 1 1 2 4

    样例输出

    3 -1

    分析:

    基本上和题2一样,询问那一段的代码改改就过了(记得改数据范围,这题数据范围比上一题大,我忘记改了,wa了还几次才发现)

    我的代码:

    #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<string> #include<vector> #include<set> #include<queue> #include<stack> #include<map> #include<string> #include<algorithm> #include<sstream> #include<memory> #include<utility> #include<functional> #include<iterator> typedef long long ll; const int inf=0x3f3f3f3f; const int inn=0x80808080; using namespace std; const int maxm=1e5+5; int a[maxm]; int add[maxm]; int belong[maxm]; int l[maxm],r[maxm]; int block,num; int n; vector<int>temp[400]; void reset(int pos){ temp[pos].clear(); for(int i=l[pos];i<=r[pos];i++){ temp[pos].push_back(a[i]); } sort(temp[pos].begin(),temp[pos].end()); } void build(){ block=sqrt(n); num=n/block; if(n%block)num++; for(int i=1;i<=num;i++){ l[i]=(i-1)*block+1; r[i]=i*block; add[i]=0; reset(i);// } r[num]=n; for(int i=1;i<=n;i++){ belong[i]=(i-1)/block+1; } } void update(int x,int y,int val){ if(belong[x]==belong[y]){ for(int i=x;i<=y;i++){ a[i]+=val; } reset(belong[x]); return ; } for(int i=x;i<=r[belong[x]];i++){ a[i]+=val; } reset(belong[x]); for(int i=l[belong[y]];i<=y;i++){ a[i]+=val; } reset(belong[y]); for(int i=belong[x]+1;i<belong[y];i++){ add[i]+=val; } } int ask(int x,int y,int val){ int ans=inn; if(belong[x]==belong[y]){ for(int i=x;i<=y;i++){ int t=a[i]+add[belong[i]]; if(t<val&&t>ans){ ans=t; } } if(ans==inn){ return -1; }else{ return ans; } } for(int i=x;i<=r[belong[x]];i++){ int t=a[i]+add[belong[i]]; if(t<val&&t>ans){ ans=t; } } for(int i=l[belong[y]];i<=y;i++){ int t=a[i]+add[belong[i]]; if(t<val&&t>ans){ ans=t; } } for(int i=belong[x]+1;i<belong[y];i++){ int t=lower_bound(temp[i].begin(),temp[i].end(),val-add[i])-temp[i].begin()-1; if(t>=0&&temp[i][t]+add[i]>ans){ ans=temp[i][t]+add[i]; } } if(ans==inn){ return -1; }else{ return ans; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(); while(n--){ int d,x,y,c; scanf("%d%d%d%d",&d,&x,&y,&c); if(d==0){ update(x,y,c); }else{ printf("%d\n",ask(x,y,c)); } } return 0; }
    最新回复(0)