用set维护有序序列
或许sort也可以,但这题的前驱定义是严格小于
所以要去重
然后就是记得自己打的加法tag在query的时候一定要算上
话说这题数据有点fake啊忘了查询算上自己的标记了还有70
然后还有玄学优化
块的大小从\( \sqrt x \)变成1000每个点能快300ms的样子qwq
似乎原理是减少维护的set的个数吧
#include <cstdio> #include <algorithm> #include <cstring> #include <set> #include <cmath> using namespace std; const int MAXN = 101000; int n,sz,num,tag[MAXN],a[MAXN],belong[MAXN]; set<int> b[MAXN]; void calbe(int n){ for(int i=1;i<=n;i++) belong[i]=(i-1)/sz+1; } void reset(int x){ b[x].clear(); for(int i=(x-1)*sz+1;i<=min(x*sz,n);i++) b[x].insert(a[i]); } void update(int l,int r,int w){ int xl=belong[l]; int xr=belong[r]; for(int i=l;i<=min(xl*sz,r);i++) a[i]+=w; reset(xl); if(xl!=xr){ for(int i=(xr-1)*sz+1;i<=r;i++) a[i]+=w; reset(xr); } for(int i=xl+1;i<=xr-1;i++) tag[i]+=w; } int query(int l,int r,int w){ int xl=belong[l]; int xr=belong[r]; int ans=-1; for(int i=l;i<=min(r,xl*sz);i++) if(a[i]<w-tag[xl]&&a[i]+tag[xl]>ans) ans=a[i]+tag[xl]; if(xl!=xr){ for(int i=(xr-1)*sz+1;i<=r;i++) if(a[i]<w-tag[xr]&&a[i]+tag[xr]>ans) ans=a[i]+tag[xr]; } for(int i=xl+1;i<=xr-1;i++){ set<int> :: iterator it=b[i].lower_bound(w-tag[i]); if(it==b[i].begin()) continue; it--; if(ans<(*it+tag[i])) ans=*it+tag[i]; } return ans; } int main(){ scanf("%d",&n); sz=sqrt(n); calbe(n); num=n/sz; if(n%sz) num++; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=num;i++){ reset(i); } for(int i=1;i<=n;i++){ int opt,l,r,c; scanf("%d %d %d %d",&opt,&l,&r,&c); if(opt==0) update(l,r,c); else printf("%d\n",query(l,r,c)); } return 0; }