P13978题解
题目链接
这是一道比较复杂的分块问题。这个思路还是很朴素的每个块排序加二分处理。
整块查询方式:我们在分块时顺手排一下块内元素的序,每次查询时只需二分比目标小的第一个数即可。
散块查询方式:喜闻乐见的暴力查找。
整块处理方式:直接加懒标记即可。
散块处理方式:每个单独加,然后重新排序一下这个块。
注意事项:
1.不要像作者一样忘记写分块直接处理啊。
2.二分处理的时候一定要注意会不会超限。
#include <bits/stdc++.h>
#define mx(x,y) x>y?x:y
using namespace std;
const int N=4e5+10;
long long n,a[N],len,L[N],R[N],tag[N],pos[N],op,l,r,x,cnt,ma,tmp;
vector<long long>v[N];
inline void biuld(){len=sqrt(n);while(1){++cnt, L[cnt]=R[cnt-1]+1, R[cnt]=cnt*len;if(R[cnt]>=n){R[cnt]=n;break;}}for(register int i=1;i<=cnt;++i){for(register int j=L[i];j<=R[i];++j){pos[j]=i, v[i].emplace_back(a[j]); }sort(v[i].begin(),v[i].end());}
}
inline void change(int x){v[x].clear();for(register int i=L[x];i<=R[x];++i){v[x].emplace_back(a[i]);}sort(v[x].begin(),v[x].end());
}
inline void update(long long l, long long r, long long x){if(pos[l]==pos[r]){for(int i=l;i<=r;++i) a[i]+=x;change(pos[l]);return;}for(register int i=l;i<=R[pos[l]];++i) a[i]+=x;for(register int i=pos[l]+1;i<pos[r];++i) tag[i]+=x;for(register int i=L[pos[r]];i<=r;++i) a[i]+=x;change(pos[l]), change(pos[r]);
}
inline long long find(long long l, long long r, long long x){ma=INT_MIN;if(pos[l]==pos[r]){for(register int i=l;i<=r;++i){if(a[i]+tag[pos[l]]<x) ma=mx(ma,a[i]+tag[pos[l]]);}return ma;}for(register int i=l;i<=R[pos[l]];++i) if(a[i]+tag[pos[l]]<x) ma=mx(ma,a[i]+tag[pos[l]]);for(register int i=pos[l]+1;i<pos[r];++i){auto p=lower_bound(v[i].begin(),v[i].end(),x-tag[i])-v[i].begin()-1;if(p>=0) ma=mx(ma,v[i][p]+tag[i]);}for(register int i=L[pos[r]];i<=r;++i) if(a[i]+tag[pos[r]]<x) ma=mx(ma,a[i]+tag[pos[r]]);return ma;
}
inline long long read(){char c=getchar(); long long k=0,f=1;while(c<'0'||c>'9'){if(c=='-'){f=-1;}c=getchar();}while(c>='0'&&c<='9') k=k*10+c-'0', c=getchar();return k*f;
}
signed main(){cin>>n;for(register int i=1;i<=n;++i) a[i]=read();biuld();for(register int i=1;i<=n;++i){op=read(), l=read(), r=read(), x=read();if(!op) update(l,r,x);else{tmp=find(l,r,x);if(tmp==INT_MIN) printf("-1\n");else printf("%lld\n",tmp);}}return 0;
}
可以看出因为没有加biuld作者为卡常拼尽了全力。