题解:P13978 数列分块入门 3

· · 题解

和上一道差不多呀!

做法

考虑分块。维护两个数组,一个是原数组,一个是块内排序后的数组。对于散块修改,直接暴力加。对于整块修改,在 tag 上加。对于散块查询,直接暴力查询最大的 \le x 的数。对于整块查询,在排好序的数组上二分最后一个小于

## 代码 ```cpp #include<bits/stdc++.h> #define int long long #define debug(x) cerr<<#x<<"="<<(x)<<'\n' #define rep(i,a,b) for(int i=a;i<=b;++i) using namespace std; const int N=3e5+5,B=500,mod=10007; int n,tot; int a[N],b[N],L[B],R[B],bel[N],tag[N]; inline void reset(int id){ rep(i,L[id],R[id]) b[i]=a[i]; sort(b+L[id],b+R[id]+1); } inline void add(int l,int r,int x){ if(bel[l]==bel[r]){ rep(i,l,r) a[i]+=x; reset(bel[l]); return; } rep(i,l,R[bel[l]]) a[i]+=x; rep(i,L[bel[r]],r) a[i]+=x; rep(i,bel[l]+1,bel[r]-1) tag[i]+=x; reset(bel[l]),reset(bel[r]); } inline int query(int l,int r,int x){ int ans=-0x3f3f3f3f3f3f3f3f; if(bel[l]==bel[r]){ rep(i,l,r) if(a[i]+tag[bel[i]]<x) ans=max(ans,a[i]+tag[bel[i]]); return ans!=-0x3f3f3f3f3f3f3f3f?ans:-1; } rep(i,l,R[bel[l]]) if(a[i]+tag[bel[i]]<x) ans=max(ans,a[i]+tag[bel[i]]); rep(i,L[bel[r]],r) if(a[i]+tag[bel[i]]<x) ans=max(ans,a[i]+tag[bel[i]]); rep(i,bel[l]+1,bel[r]-1){ int pos=lower_bound(b+L[i],b+R[i]+1,x-tag[i])-b-1; if(pos>=L[i]) ans=max(ans,b[pos]+tag[i]); } return ans!=-0x3f3f3f3f3f3f3f3f?ans:-1; } signed main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); cin>>n; rep(i,1,n) cin>>a[i],b[i]=a[i],bel[i]=i/B; rep(i,1,n) if(!L[bel[i]]) L[bel[i]]=i; for(int i=n;i>=1;--i) if(!R[bel[i]]) R[bel[i]]=i; tot=bel[n]; rep(i,1,tot-1) sort(b+L[i],b+R[i]+1); rep(i,1,n){ int op,l,r,x; cin>>op>>l>>r>>x; if(!op){ add(l,r,x); }else{ cout<<query(l,r,x)<<'\n'; } } return 0; } ```